129 【战斗】战斗系统-服务端(反击改为使用普攻,去除通用反击技能设定;武将特长支持;)
| | |
| | | dict BatAttrDict; //其他战斗属性字典 {"属性ID":值, ...}
|
| | | list FetterIDList; //羁绊ID列表
|
| | | BYTE RecruitBySelf; // 招募需要本体
|
| | | BYTE Specialty; // 武将特长
|
| | | };
|
| | |
|
| | | //武将星级天赋表
|
| | |
| | | #NPC读表取
|
| | | return attack.GetHurtType()
|
| | |
|
| | | def GetAtkDistType(curObj):
|
| | | ## 获取是近战还是远程,默认近战
|
| | | if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
|
| | | return ChConfig.AtkDistType_Short
|
| | | |
| | | playerID = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID)
|
| | | if not playerID:
|
| | | return ChConfig.AtkDistType_Short
|
| | | |
| | | heroID = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
|
| | | if heroID:
|
| | | heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
|
| | | if heroIpyData:
|
| | | return heroIpyData.GetAtkDistType()
|
| | | |
| | | npcID = curObj.GetNPCID()
|
| | | npcDataEx = NPCCommon.GetNPCDataPy(npcID)
|
| | | if npcDataEx:
|
| | | return npcDataEx.GetAtkDistType()
|
| | | |
| | | return ChConfig.AtkDistType_Short
|
| | |
|
| | | #--------------------------------------------------------------------------
|
| | | ## 设置玩家进入战斗状态
|
| | | # @param defender 当前玩家(被攻击了)
|
| | |
| | | self.skinID = 0
|
| | | self.country = 0
|
| | | self.atkDistType = 0
|
| | | self.specialty = 0 # 特长
|
| | | self.sex = 0
|
| | | self.lv = 1
|
| | | self.fightPower = 0
|
| | |
| | | def SetCountry(self, country): self.country = country
|
| | | def GetAtkDistType(self): return self.atkDistType
|
| | | def SetAtkDistType(self, atkDistType): self.atkDistType = atkDistType
|
| | | def GetSpecialty(self): return self.specialty
|
| | | def SetSpecialty(self, specialty): self.specialty = specialty
|
| | | def GetSex(self): return self.sex
|
| | | def SetSex(self, sex): self.sex = sex
|
| | | def GetNPCID(self): return self.npcID # 如果是NPC战斗单位,则该值非0
|
| | |
| | |
|
| | | batObjMgr = BattleObj.GetBatObjMgr()
|
| | | initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
|
| | | atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 2)
|
| | | for posNumKey, heroInfo in heroDict.items():
|
| | | posNum = int(posNumKey)
|
| | |
|
| | | atkBackSkillID = 0 # 反击技能ID
|
| | | fightPower = 0
|
| | | skillIDList = [] # 战斗对象可能改变属性或技能,重新创建,防止误修改来源值
|
| | | attrDict = {}
|
| | |
| | | lv = heroInfo.get("LV", 1)
|
| | | heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None
|
| | | if heroIpyData:
|
| | | specialty = heroIpyData.GetSpecialty()
|
| | | atkDistType = heroIpyData.GetAtkDistType()
|
| | | objName = heroIpyData.GetName()
|
| | | country = heroIpyData.GetCountry()
|
| | |
| | | if not npcDataEx:
|
| | | continue
|
| | | if not heroIpyData:
|
| | | specialty = 0
|
| | | atkDistType = npcDataEx.GetAtkDistType()
|
| | | objName = npcDataEx.GetNPCName()
|
| | | country = npcDataEx.GetCountry()
|
| | |
| | | batObj.SetFightPower(fightPower)
|
| | | batObj.SetLV(lv)
|
| | | batObj.SetAtkDistType(atkDistType)
|
| | | batObj.SetSpecialty(specialty)
|
| | | batObj.SetCountry(country)
|
| | | batObj.SetSex(sex)
|
| | | batObj.SetHero(heroID, skinID)
|
| | |
|
| | | if atkDistType == ChConfig.AtkDistType_Short:
|
| | | atkBackSkillID = atkBackSkillIDList[0] if len(atkBackSkillIDList) > 0 else 0
|
| | | elif atkDistType == ChConfig.AtkDistType_Long:
|
| | | atkBackSkillID = atkBackSkillIDList[1] if len(atkBackSkillIDList) > 1 else 0
|
| | | if atkBackSkillID:
|
| | | skillIDList.append(atkBackSkillID)
|
| | | skillManager = batObj.GetSkillManager()
|
| | | skillManager.SkillReset()
|
| | | for skillID in skillIDList:
|
| | |
| | | HurtType_3,
|
| | | HurtType_4,
|
| | | HurtType_Parry, # 格挡 5
|
| | | HurtType_IgnoreDef, # 无视防御 6
|
| | | HurtType_IgnoreDef, # 无视防御/真实伤害 6
|
| | | HurtType_SuperHit, # 暴击 7
|
| | | HurtType_8,
|
| | | HurtType_Stun, # 击晕 8 仅算概率触发的击晕,技能额外击晕效果的不算
|
| | | HurtType_Miss, # 闪避 9
|
| | | ) = range(10)
|
| | |
|
| | |
| | | Def_SkillFuncType_TurnNormaSkill, #1 普攻技能
|
| | | Def_SkillFuncType_AngerSkill, #2 怒气技能
|
| | | Def_SkillFuncType_PotentialSkill, #3 潜能技能
|
| | | Def_SkillFuncType_AtkbackSkill, #4 反击技能
|
| | | ) = range(5)
|
| | | ) = range(4)
|
| | |
|
| | | # MMO项目 - 先保留,重新定义从1000开始,后续可陆续删除
|
| | | (Def_SkillFuncType_Common, #0为通用技能
|
| | |
| | | AtkDistType_Long, # 远程
|
| | | ) = range(1, 1 + 2)
|
| | |
|
| | | # 武将特长
|
| | | HeroSpecialtyList = (
|
| | | HeroSpecialty_Stun, # 击晕 1
|
| | | HeroSpecialty_SuperHit, # 暴击 2
|
| | | HeroSpecialty_Combo, # 连击 3
|
| | | HeroSpecialty_Miss, # 闪避 4
|
| | | HeroSpecialty_Parry, # 格挡 5
|
| | | HeroSpecialty_SuckHP, # 吸血 6
|
| | | ) = range(1, 1 + 6)
|
| | |
|
| | | # 经验倍率限制类型
|
| | | (
|
| | | ExpRateLimitType_Recover, # 资源找回
|
| | |
| | | ("dict", "BatAttrDict", 0),
|
| | | ("list", "FetterIDList", 0),
|
| | | ("BYTE", "RecruitBySelf", 0),
|
| | | ("BYTE", "Specialty", 0),
|
| | | ),
|
| | |
|
| | | "HeroTalent":(
|
| | |
| | | def GetHPInheritPer(self): return self.attrTuple[11] # 生命继承 WORD
|
| | | def GetBatAttrDict(self): return self.attrTuple[12] # 其他战斗属性字典 {"属性ID":值, ...} dict
|
| | | def GetFetterIDList(self): return self.attrTuple[13] # 羁绊ID列表 list
|
| | | def GetRecruitBySelf(self): return self.attrTuple[14] # 招募需要本体 BYTE |
| | | def GetRecruitBySelf(self): return self.attrTuple[14] # 招募需要本体 BYTE
|
| | | def GetSpecialty(self): return self.attrTuple[15] # 武将特长 BYTE |
| | | |
| | | # 武将星级天赋表 |
| | | class IPY_HeroTalent(): |
| | |
| | | ## 是否回合普攻技能,区别与无技能的普通A一下,该普攻同样可以有各种技能效果,只是他属于普攻
|
| | | return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_TurnNormaSkill
|
| | |
|
| | | def isAtkbackSkill(curSkill):
|
| | | ## 是否反击技能
|
| | | return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill
|
| | |
|
| | | ## 检查技能是否为被动技能, 用于控制不可释放技能
|
| | | def isPassiveSkill(curSkill):
|
| | | return curSkill.GetSkillType() in [ChConfig.Def_SkillType_Passive,
|
| | |
| | | if CanCombo(curBatObj, tagObj):
|
| | | # 连击根据技能目标配置逻辑重新选择目标
|
| | | GameWorld.DebugLog("● %s 【连击】" % TurnAttack.GetObjName(curBatObj))
|
| | | DoHeroSpecialty(turnFight, curBatObj, ChConfig.HeroSpecialty_Combo, useSkill.GetSkillID())
|
| | | OnUseSkill(turnFight, curBatObj, useSkill, batType=ChConfig.TurnBattleType_Combo)
|
| | |
|
| | | return
|
| | |
| | | return
|
| | |
|
| | | tagID = tagObj.GetID()
|
| | | if tagObj.GetAtkDistType() != ChConfig.AtkDistType_Short:
|
| | | GameWorld.DebugLog("非近战不可反击! tagID=%s" % tagID)
|
| | | canAtkbackDictTypeList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 2)
|
| | | if tagObj.GetAtkDistType() not in canAtkbackDictTypeList:
|
| | | GameWorld.DebugLog("该远近类型武将不可反击! tagID=%s,AtkDistType=%s not in %s" % (tagID, tagObj.GetAtkDistType(), canAtkbackDictTypeList))
|
| | | return
|
| | |
|
| | | canAtkBack = False
|
| | |
| | | useSkill = skillManager.GetSkillByIndex(index)
|
| | | if not useSkill:
|
| | | continue
|
| | | if useSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill:
|
| | | if useSkill.GetFuncType() == ChConfig.Def_SkillFuncType_TurnNormaSkill: # 使用普攻反击
|
| | | GameWorld.DebugLog("可以反击! tagID=%s" % tagID)
|
| | | return useSkill
|
| | | return
|
| | |
| | | TurnAttack.SetObjKilled(turnFight, curObj)
|
| | |
|
| | | # 统计伤血,可能单个技能对同一目标造成多次伤害
|
| | | isSuperHit, isStun, isSuckHP = False, False, False
|
| | | missObjIDList = []
|
| | | for hurtObj in useSkill.GetHurtObjList():
|
| | | hurtObjID = hurtObj.GetObjID()
|
| | |
| | | __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
|
| | | missObjIDList.append(hurtObjID)
|
| | | |
| | | DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Miss, relatedSkillID)
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Parry):
|
| | | DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Parry, relatedSkillID)
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_SuperHit):
|
| | | isSuperHit = True
|
| | | if hurtObj.HaveHurtType(ChConfig.HurtType_Stun):
|
| | | isStun = True
|
| | | if hurtObj.GetSuckHP() > 0:
|
| | | isSuckHP = True
|
| | | # 群攻只触发一次特长
|
| | | if isSuperHit:
|
| | | DoHeroSpecialty(turnFight, curObj, ChConfig.HeroSpecialty_SuperHit, relatedSkillID)
|
| | | if isStun:
|
| | | DoHeroSpecialty(turnFight, curObj, ChConfig.HeroSpecialty_Stun, relatedSkillID)
|
| | | if isSuckHP:
|
| | | DoHeroSpecialty(turnFight, curObj, ChConfig.HeroSpecialty_SuckHP, relatedSkillID)
|
| | | |
| | | # 结算副本相关的攻击结果,仅主动发起玩家阵容武将触发
|
| | | curPlayer = turnFight.curPlayer
|
| | | if curPlayer and curObj and curObj.GetOwnerID() == curPlayer.GetPlayerID():
|
| | |
| | | ## 技能释放者怒气相关
|
| | | if SkillCommon.isAngerSkill(useSkill):
|
| | | curBatObj.SetXP(0)
|
| | | elif SkillCommon.isTurnNormalSkill(useSkill):
|
| | | elif SkillCommon.isTurnNormalSkill(useSkill) and useSkill.GetBatType() == ChConfig.TurnBattleType_Normal:
|
| | | addXP = IpyGameDataPY.GetFuncCfg("AngerXP", 3)
|
| | | AddTurnFightXP(curBatObj, addXP, "skillID:%s" % useSkill.GetSkillID())
|
| | | return
|
| | |
| | | updXP = curXP + addXP
|
| | | gameObj.SetXP(updXP)
|
| | | GameWorld.DebugLog(" 更新XP: curID=%s,curXP=%s,addXP=%s,updXP=%s,reason=%s" % (gameObj.GetID(), curXP, addXP, updXP, reason))
|
| | | return
|
| | |
|
| | | def DoHeroSpecialty(turnFight, gameObj, specialty, relatedSkillID=0):
|
| | | ## 执行武将特长
|
| | | if gameObj.GetSpecialty() != specialty:
|
| | | return
|
| | | specialtyAddXPDict = IpyGameDataPY.GetFuncEvalCfg("AngerXP", 5, {})
|
| | | if str(specialty) not in specialtyAddXPDict:
|
| | | return
|
| | | addXP = specialtyAddXPDict[str(specialty)]
|
| | | curXP = gameObj.GetXP()
|
| | | updXP = curXP + addXP
|
| | | gameObj.SetXP(updXP, False)
|
| | | GameWorld.DebugLog(" 特长加XP: curID=%s,curXP=%s,addXP=%s,updXP=%s,特性=%s" % (gameObj.GetID(), curXP, addXP, updXP, specialty))
|
| | | Sync_PropertyRefreshView(turnFight, gameObj, ChConfig.AttrID_XP, updXP, addXP, diffType=1, relatedSkillID=relatedSkillID)
|
| | | return
|
| | |
|
| | | def __DoCurSkillEff(turnFight, curObj, useSkill, missObjIDList):
|
| | |
| | | skillID = curSkill.GetSkillID()
|
| | | isTurnNormalSkill = SkillCommon.isTurnNormalSkill(curSkill)
|
| | | isAngerSkill = SkillCommon.isAngerSkill(curSkill)
|
| | | isAtkbackSkill = SkillCommon.isAtkbackSkill(curSkill)
|
| | | isDot = ("damageoftime" in kwargs)
|
| | | angerOverflow = 0 # 怒气溢出值
|
| | |
|
| | |
| | |
|
| | | #calcType = curSkill.GetCalcType() 目前暂时按攻击算伤害,之后可以扩展其他
|
| | |
|
| | | isSuperHit, isParry = False, False
|
| | | isSuperHit, isParry, isStun = False, False, False
|
| | | aSuperDamPer, dSuperDamPerDef = 0, 0
|
| | | if not isDot:
|
| | | isSuperHit = CanSuperHit(atkObj, defObj) # 是否暴击
|
| | | isParry = (isTurnNormalSkill and CanParry(atkObj, defObj)) # 是否格挡,仅针对普攻
|
| | | CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
|
| | | isStun = CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
|
| | |
|
| | | if isSuperHit:
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_SuperHit)
|
| | |
| | |
|
| | | if ignoreDef:
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_IgnoreDef)
|
| | | |
| | | if isStun:
|
| | | hurtTypes |= pow(2, ChConfig.HurtType_Stun)
|
| | |
|
| | | #参与运算的数值
|
| | | #rand = random.random() #种子数 0~1
|
| | |
| | | elif isAngerSkill:
|
| | | hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 2))
|
| | | GameWorld.DebugLog(" 怒气技能伤害=%s" % (hurtValue))
|
| | | elif isAtkbackSkill:
|
| | | hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 3))
|
| | | GameWorld.DebugLog(" 反击伤害=%s" % (hurtValue))
|
| | | else:
|
| | | hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 4))
|
| | | GameWorld.DebugLog(" 其他伤害=%s" % (hurtValue))
|