From f198885f31c9c7eb19eb28adce562e39e64d581c Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期五, 18 七月 2025 16:23:11 +0800 Subject: [PATCH] 121 【武将】武将系统-服务端(属性计算、战斗力计算;新角色初始给默认装备、默认阵容武将;) --- ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py | 619 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 605 insertions(+), 14 deletions(-) diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py index ef64c77..0c96bc7 100644 --- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py +++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py @@ -9,7 +9,7 @@ # @date 2025-07-02 # @version 1.0 # -# 详细描述: 在线玩家管理,用于管理在线玩家、准在线玩家的临时数据 +# 详细描述: 在线玩家管理,用于管理在线玩家、准在线玩家的临时数据,重读不会被重置 # 准在线玩家 - 实际不在线,x分钟内离线的玩家,用于支持断线重连,短时间内临时数据可持续 # #------------------------------------------------------------------------------- @@ -18,28 +18,222 @@ import TurnAttack import PyGameData +import ShareDefine +import PlayerControl +import IpyGameDataPY +import FormulaControl +import PlayerHero +import GameWorld +import ChConfig +import ChEquip import time +class LineupHero(): + ## 阵容战斗武将,注意:同一个武将在不同阵容中可能属性不一样 + + def __init__(self): + self.Clear() + return + + def Clear(self): + self.itemIndex = 0 + self.heroID = 0 + self.posNum = 0 + self.heroBatAttrDict = {} # 武将的最终战斗属性字典, {attrID:value, ...} + self.heroSkillIDList = [] # 武将拥有的技能ID列表 [skillID, ...] + self.fightPower = 0 # 武将最终战力 + return + +class Lineup(): + ## 阵容 + + def __init__(self, playerID, lineupID): + self.playerID = playerID + self.lineupID = lineupID + self.olPlayer = None + self.shapeType = 0 + self.heroItemDict = {} # 阵容武将背包索引信息 {itemIndex:posNum, ...} + self.__refreshState = 0 # 刷属性标记, 0-不需要刷新了,1-需要刷新 + + self.__freeLineupHeroObjs = [] # 释放的空闲对象[LineupHero, ...] + self.lineupHeroDict = {} # 阵容武将 {posNum:LineupHero, ...} + self.fightPower = 0 # 阵容总战力 + return + + def UpdLineup(self, heroItemDict, shapeType=0, refreshForce=False): + '''变更阵容时更新 + @param heroItemDict: 武将背包索引信息 {itemIndex:posNum, ...} + @param shapeType: 阵型 + @param refreshForce: 是否强制刷属性 + ''' + self.shapeType = shapeType + self.heroItemDict = heroItemDict + GameWorld.DebugLog("更新阵容: lineupID=%s,%s" % (self.lineupID, heroItemDict), self.playerID) + self.RefreshLineupAttr(refreshForce) + return + + def FreeLineupHero(self): + ## 释放阵容武将对象,重新计算 + for freeObj in self.lineupHeroDict.values(): + if freeObj not in self.__freeLineupHeroObjs: + self.__freeLineupHeroObjs.append(freeObj) + self.lineupHeroDict = {} + self.fightPower = 0 + return + + def GetLineupHero(self, posNum): + lineupHero = None + if posNum in self.lineupHeroDict: + lineupHero = self.lineupHeroDict[posNum] + elif self.__freeLineupHeroObjs: + lineupHero = self.__freeLineupHeroObjs.pop(0) + lineupHero.Clear() + self.lineupHeroDict[posNum] = lineupHero + else: + lineupHero = LineupHero() + self.lineupHeroDict[posNum] = lineupHero + return lineupHero + + def GetLineupHeroByID(self, heroID): + for posNum in self.lineupHeroDict.keys(): + lineup = self.GetLineupHero(posNum) + if lineup.heroID == heroID: + return lineup + return + + def GetLineupInfo(self): + ## 获取阵容信息,即要用到该阵容了,如战斗或者保存缓存信息等 + self.DoRefreshLineupAttr() # 取阵容时先检查 + return + + def SetNeedRefreshState(self): + ## 设置需要刷属性 + self.__refreshState = 1 + return + + def RefreshLineupAttr(self, refreshForce=False): + self.__refreshState = 1 # 标记要刷新 + if refreshForce: + self.DoRefreshLineupAttr() + return + + def DoRefreshLineupAttr(self): + if not self.__refreshState: + return False + doRefreshLineupAttr(self.olPlayer.curPlayer, self.olPlayer, self) + self.__refreshState = 0 + return True + + def CheckHeroItemUpdate(self, itemIndex): + if itemIndex not in self.heroItemDict: + return + self.RefreshLineupAttr() + return True + class OnlinePlayer(): - ## 准在线玩家临时数据 + ## 玩家在线临时数据,主要时数据的缓存,逻辑可不在类中处理,方便重读脚本时测试 def __init__(self, playerID): self.playerID = playerID + self.curPlayer = None + + # 属性、阵容 + self.calcAttrDict = {} # 非武将功能点属性统计 {calcIndex:{attrID:value, ...}, ...} + self.lineupDict = {} # 上阵阵容 {lineupID:Lineup, ...} + + # 主线战斗 self.mainFight = TurnAttack.MainFight(playerID) - return - - def OnPlayerLogin(self, curPlayer): - self.mainFight.playerLogin(curPlayer) - return - - def OnPlayerOffline(self, curPlayer): - self.mainFight.playerOffline(curPlayer) return def OnClear(self): self.mainFight.clear() return + + def SetPlayer(self, curPlayer): + self.curPlayer = curPlayer + self.mainFight.turnFight.curPlayer = curPlayer + return + + def IsRealOnline(self): + ## 是否真的在线 + return self.curPlayer != None + + def GetLineup(self, lineupID): + lineup = None + if lineupID in self.lineupDict: + lineup = self.lineupDict[lineupID] + else: + lineup = Lineup(self.playerID, lineupID) + self.lineupDict[lineupID] = lineup + lineup.olPlayer = self + return lineup + + def GetCalcAttr(self, calcIndex): return self.calcAttrDict.get(calcIndex, {}) + def SetCalcAttr(self, calcIndex, attrDict): + ## 设置某个功能点计算的属性 + self.calcAttrDict[calcIndex] = attrDict + return + + def ReCalcAllAttr(self): + ## 重置所有功能点计算的属性,一般登录的时候调用一次即可,其他单功能刷新的话一般使用 RefreshRoleAttr + curPlayer = self.curPlayer + GameWorld.DebugLog("ReCalcAllAttr...", self.playerID) + + self.calcAttrDict = {} + self.lineupDict = {} + + doCalcAllAttr(curPlayer) + doReloadLineup(curPlayer, self) + + self.RefreshRoleAttr() + return + + def RefreshRoleAttr(self, refreshForce=False, isAllLineup=False): + '''刷新主公属性,影响主公属性的功能点属性变化时统一调用此函数 + @param refreshForce: 是否强制立马刷新 + @param isAllLineup: 是否只同步刷所有阵容属性,如果设置False则默认仅刷主阵容属性 + ''' + GameWorld.DebugLog("请求刷属性: refreshForce=%s" % (refreshForce), self.playerID) + # 主公属性刷新时,所有阵容都要同步刷新 + for lineup in self.lineupDict.values(): + lineup.SetNeedRefreshState() + + if refreshForce: + self.DoRefreshRoleAttr(isAllLineup) + return + + def DoRefreshRoleAttr(self, isAllLineup=False): + '''执行刷属性,默认额外刷主阵容,其他阵容可以用到的时候再刷新 + @param isAllLineup: 是否刷所有阵容,如果设置False则默认仅刷主阵容属性 + @return: 是否有刷属性,0-无;1-有 + ''' + + isRefresh = False + # 同步执行阵容属性刷新 + for lineupID, lineup in self.lineupDict.items(): + if not isAllLineup and lineupID != ShareDefine.Lineup_Main: + continue + if lineup.DoRefreshLineupAttr(): + isRefresh = True + + return isRefresh + + def OnHeroItemUpate(self, itemIndexList): + '''武将物品养成更新 + @param itemIndexList: 变化武将物品所在武将背包格子索引列表 + @param return: 影响的阵容ID列表 + ''' + effLineupIDList = [] + + for lineupID, lineup in self.lineupDict.items(): + for itemIndex in itemIndexList: + if lineup.CheckHeroItemUpdate(itemIndex): + if lineupID not in effLineupIDList: + effLineupIDList.append(lineupID) + + GameWorld.DebugLog("武将物品养成更新索引: %s, 影响阵容:%s" % (itemIndexList, effLineupIDList), self.playerID) + return effLineupIDList class OnlineMgr(): ## 准在线玩家管理 @@ -57,7 +251,7 @@ else: olPlayer = OnlinePlayer(playerID) self.__onlinePlayerDict[playerID] = olPlayer - + olPlayer.SetPlayer(curPlayer) return olPlayer def SetPlayerOnline(self, curPlayer): @@ -69,7 +263,7 @@ self.__onlinePlayerDict[playerID] = olPlayer else: olPlayer = self.__onlinePlayerDict[playerID] - olPlayer.OnPlayerLogin(curPlayer) + olPlayer.SetPlayer(curPlayer) return def SetPlayerOffline(self, curPlayer): @@ -78,7 +272,7 @@ if playerID not in self.__onlinePlayerDict: return olPlayer = self.__onlinePlayerDict[playerID] - olPlayer.OnPlayerOffline(curPlayer) + olPlayer.SetPlayer(None) self.__offlinePlayerTimeDict[playerID] = int(time.time()) return @@ -104,15 +298,412 @@ mgr = OnlineMgr() PyGameData.g_onlineMgr = mgr return mgr - + +def GetOnlinePlayer(curPlayer): return GetOnlineMgr().GetOnlinePlayer(curPlayer) + def OnPlayerLogin(curPlayer): + ## 需登录逻辑最早调用 GetOnlineMgr().SetPlayerOnline(curPlayer) return def OnPlayerLogoff(curPlayer): + ## 需下线逻辑最后调用 GetOnlineMgr().SetPlayerOffline(curPlayer) return def OnMinute(): GetOnlineMgr().ProcessOffline() return + +def CalcRoleBase(curPlayer): + playerID = curPlayer.GetID() + playerLV = curPlayer.GetLV() + lvIpyData = PlayerControl.GetPlayerLVIpyData(playerLV) + + lvAttrDict = {} + if lvIpyData: + lvAttrDict = {ChConfig.AttrID_Atk:lvIpyData.GetAtk(), + ChConfig.AttrID_Def:lvIpyData.GetDef(), + ChConfig.AttrID_MaxHP:lvIpyData.GetMaxHP() + } + + GameWorld.DebugLog("角色等级属性: %s" % lvAttrDict, playerID) + GetOnlinePlayer(curPlayer).SetCalcAttr(ChConfig.Def_CalcAttr_LV, lvAttrDict) + return + +def doReloadLineup(curPlayer, olPlayer): + ## 重新载入阵容 + loadLineupIDList = ShareDefine.LineupList + lineupDict = {} # {阵容ID:{itemIndex:posNum, ...}, ...} + lineShapeTypeDict = {} # {阵容ID:阵型, ...} + syncItemDict = {} # 需要同步的异常物品 {index:heroItem, ...} + curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero) + for index in range(curPack.GetCount()): + heroItem = curPack.GetAt(index) + if not heroItem or heroItem.IsEmpty(): + continue + lineupCount = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroLineup) + if not lineupCount: + continue + delValueList = [] + for lpIndex in range(lineupCount)[::-1]: + lineupValue = heroItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroLineup, lpIndex) + lineupID, shapeType, posNum = PlayerHero.GetLineupValue(lineupValue) + if lineupID not in loadLineupIDList: + continue + # 任意取一个武将保存的阵型即可,同阵容的武将理论上保存的阵型是一样的 + if lineupID not in lineShapeTypeDict: + lineShapeTypeDict[lineupID] = shapeType + if lineupID not in lineupDict: + lineupDict[lineupID] = {} + heroItemDict = lineupDict[lineupID] + + # 超出人数限制或位置异常 + if len(heroItemDict) >= ShareDefine.LineupObjMax or posNum in heroItemDict.values() or index in heroItemDict: + delValueList.append(lineupValue) + else: + heroItemDict[index] = posNum + + if delValueList: + item = heroItem.GetItem() + for lineupValue in delValueList: + item.DelUserAttr(ShareDefine.Def_IudetHeroLineup, lineupValue) + syncItemDict[index] = heroItem + + for syncItem in syncItemDict.values(): + syncItem.Sync_Item() + + GameWorld.DebugLog("重载阵容: %s" % lineupDict, curPlayer.GetPlayerID()) + for lineupID, heroItemDict in lineupDict.items(): + lineup = olPlayer.GetLineup(lineupID) + + # 获取其他绑定该阵容的功能,如红颜、灵兽等 + + shapeType = lineShapeTypeDict.get(lineupID, 0) + lineup.UpdLineup(heroItemDict, shapeType) + + return + +def doCalcAllAttr(curPlayer): + ## 计算所有属性 + GameWorld.DebugLog("doCalcAllAttr...", curPlayer.GetPlayerID()) + CalcRoleBase(curPlayer) + ChEquip.CalcRoleEquipAttr(curPlayer) + PlayerHero.CalcHeroAddAttr(curPlayer) + return + +def doRefreshLineupAttr(curPlayer, olPlayer, lineup): + ''' 刷新某个阵容属性 + 基础属性-面板显示: + 1.全体基础固定值=所有穿戴装备【装备基础固定值】+【法宝基础固定值】+【红颜基础固定值】+【其它模块的固定值】 + 2.全体百分比加成=图鉴加成+【灵兽模块】+【红颜模块】+【其它模块】+所有上阵卡牌【初始加成+升级加成+突破加成+吞噬加成】 + 3.卡牌继承比例=卡牌品质及职业继承比例不同 + 4.卡牌自身培养加成=【羁绊加成%+突破词条加成%+天赋加成%】 + 最终面板生命=【E全体基础固定值】*【1+E全体百分比加成】*【卡牌自身继承比例+ 卡牌自身培养%加成】+【卡牌自身固定值】 + + 战斗属性/战斗抗性/特殊属性-面板显示: + 1.全体战斗属性值=所有穿戴装备【装备战斗属性值】+【法宝战斗属性值】+【红颜战斗属性值】+【其它模块的战斗属性】 + 2.卡牌继承比例=默认100% + 3.卡牌自身培养战斗属性=【卡牌初始战斗属性+突破词条战斗属性+天赋战斗属性+觉醒战斗属性】+【法则洗炼】+【秘能装备】+【其它模块】 + 最终面板战斗属性=【E全体战斗属性值】*【卡牌继承比例】+【卡牌自身培养战斗属性】 + ''' + playerID = curPlayer.GetPlayerID() + lineupID = lineup.lineupID + + GameWorld.DebugLog("刷新阵容属性: lineupID=%s" % lineupID, playerID) + GameWorld.DebugLog(" itemIndex-posNum : %s" % lineup.heroItemDict, playerID) + + lineup.FreeLineupHero() + + # 因为同阵容的武将ID不能重复,所以字典key可以用武将ID + countryHeroInfo = {} # 国家武将统计 {country:[heroID, ...], ...} + fetterHeroInfo = {} # 阵容羁绊武将统计信息 {fetterID:[heroID, ...], ...} + heroSelfAttrInfo = {} # 武将自身属性 {heroID:{attrID:value, ...}, ...} + heroStarTalentInfo = {} # 武将星级天赋属性 {heroID:{attrID:value, ...}, ...} + heroBreakAttrInfo = {} # 武将突破潜能属性 {heroID:{attrID:value, ...}, ...} + heroAwakeTalentInfo = {} # 武将觉醒天赋属性 {heroID:{attrID:value, ...}, ...} + + # 上阵卡牌【初始加成+升级加成+突破加成+吞噬加成】 + InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer = 0, 0, 0, 0 + + curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptHero) + for itemIndex, posNum in lineup.heroItemDict.items(): + if itemIndex < 0 or itemIndex >= curPack.GetCount(): + continue + heroItem = curPack.GetAt(itemIndex) + if not heroItem or heroItem.IsEmpty(): + continue + heroID = heroItem.GetItemTypeID() + heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) + if not heroIpyData: + continue + quality = heroIpyData.GetQuality() + qualityIpyData = IpyGameDataPY.GetIpyGameData("HeroQuality", quality) + if not qualityIpyData: + continue + + heroLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroLV) + star = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroStar) + breakLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroBreakLV) + awakeLV = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroAwakeLV) + + InitAddPer += qualityIpyData.GetInitAddPer() + LVAddPer += qualityIpyData.GetLVAddPer() * heroLV + BreakLVAddPer += qualityIpyData.GetBreakLVAddPer() * breakLV + StarAddPer += qualityIpyData.GetStarAddPer() * star + + lineupHero = lineup.GetLineupHero(posNum) + #if False: + # lineupHero = LineupHero() + lineupHero.itemIndex = itemIndex + lineupHero.posNum = posNum + lineupHero.heroID = heroID + lineupHero.heroBatAttrDict = {} + lineupHero.heroSkillIDList = [] + lineupHero.fightPower = 0 + + normalSkillID = heroIpyData.GetNormalSkillID() + angerSkillID = heroIpyData.GetAngerSkillID() + lineupHero.heroSkillIDList.extend([normalSkillID, angerSkillID]) + + # 自身属性 + selfAttrDict = {} + selfAttrDict.update({ChConfig.AttrID_AtkInheritPer:heroIpyData.GetAtkInheritPer(), + ChConfig.AttrID_DefInheritPer:heroIpyData.GetDefInheritPer(), + ChConfig.AttrID_HPInheritPer:heroIpyData.GetHPInheritPer(), + }) + for k, v in heroIpyData.GetBatAttrDict().items(): + selfAttrDict[int(k)] = v + heroSelfAttrInfo[heroID] = selfAttrDict + + # 星级天赋 + starTalentAttrDict = {} + idCount = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentID) + lvCount = heroItem.GetUserAttrCount(ShareDefine.Def_IudetHeroTalentIDLV) + for aIndex in range(min(idCount, lvCount)): + talentID = heroItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentID, aIndex) + talentLV = heroItem.GetUserAttrByIndex(ShareDefine.Def_IudetHeroTalentIDLV, aIndex) + stIpyData = IpyGameDataPY.GetIpyGameData("HeroTalent", talentID) + if not stIpyData: + continue + attrID = stIpyData.GetAttrID() + attrValue = stIpyData.GetAttrValue() * talentLV + starTalentAttrDict[attrID] = starTalentAttrDict.get(attrID, 0) + attrValue + heroStarTalentInfo[heroID] = starTalentAttrDict + + # 突破潜能 + breakAttrDict = {} + awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroBreak", heroID) + if awakeIpyDataList: + for breakIpyData in awakeIpyDataList: + if breakIpyData.GetBreakLV() > breakLV: + break + attrIDList = breakIpyData.GetAttrIDList() + attrValueList = breakIpyData.GetAttrValueList() + for aIndex in range(min(len(attrIDList), len(attrValueList))): + attrID = attrIDList[aIndex] + attrValue = attrValueList[aIndex] + breakAttrDict[attrID] = breakAttrDict.get(attrID, 0) + attrValue + skillID = breakIpyData.GetSkillID() + if skillID: + lineupHero.heroSkillIDList.append(skillID) + heroBreakAttrInfo[heroID] = breakAttrDict + + # 觉醒天赋 + awakeTalentAttrDict = {} + awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID) + if awakeIpyDataList: + for awakeIpyData in awakeIpyDataList: + if awakeIpyData.GetAwakeLV() > awakeLV: + break + attrIDList = awakeIpyData.GetAttrIDList() + attrValueList = awakeIpyData.GetAttrValueList() + for aIndex in range(min(len(attrIDList), len(attrValueList))): + attrID = attrIDList[aIndex] + attrValue = attrValueList[aIndex] + awakeTalentAttrDict[attrID] = awakeTalentAttrDict.get(attrID, 0) + attrValue + skillID = awakeIpyData.GetSkillID() + if skillID: + lineupHero.heroSkillIDList.append(skillID) + heroAwakeTalentInfo[heroID] = awakeTalentAttrDict + + # 羁绊统计 + for fetterID in heroIpyData.GetFetterIDList(): + if fetterID not in fetterHeroInfo: + fetterHeroInfo[fetterID] = [] + fetterHeroIDList = fetterHeroInfo[fetterID] + if heroID not in fetterHeroIDList: + fetterHeroIDList.append(heroID) + + # 国家统计 + country = heroIpyData.GetCountry() + if country not in countryHeroInfo: + countryHeroInfo[country] = [] + countryHeroIDList = countryHeroInfo[country] + if heroID not in countryHeroIDList: + countryHeroIDList.append(heroID) + + # 羁绊属性 - 仅羁绊相关武将有效 + heroFetterAttrInfo = {} # 武将羁绊属性 {heroID:{attrID:value, ...}, ...} + for fetterID, fetterHeroIDList in fetterHeroInfo.items(): + fetterIpyData = IpyGameDataPY.GetIpyGameData("HeroFetter", fetterID) + if not fetterIpyData: + continue + needHeroIDList = fetterIpyData.GetHeroIDList() + canFetter = True + for needHeroID in needHeroIDList: + if needHeroID not in fetterHeroIDList: + canFetter = False + break + if not canFetter: + continue + attrIDList = fetterIpyData.GetAttrIDList() + attrValueList = fetterIpyData.GetAttrValueList() + for aIndex in range(min(len(attrIDList), len(attrValueList))): + attrID = attrIDList[aIndex] + attrValue = attrValueList[aIndex] + for heroID in needHeroIDList: + if heroID not in heroFetterAttrInfo: + heroFetterAttrInfo[heroID] = {} + heroFetterAttrDict = heroFetterAttrInfo[heroID] + heroFetterAttrDict[attrID] = heroFetterAttrDict.get(attrID, 0) + attrValue + + # 阵容属性 - 阵容所有武将有效 + lineupHaloAttrInfo = {} # 阵容光环属性 {attrID:value, ...} + for country, countryHeroIDList in countryHeroInfo.items(): + haloIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroLineupHalo", country) + if not haloIpyDataList: + continue + + attrIDList, attrValueList = [], [] + countryHeroCnt = len(countryHeroIDList) + for haloIpyData in haloIpyDataList: + needHeroCount = haloIpyData.GetNeedHeroCount() + if countryHeroCnt < needHeroCount: + break + attrIDList = haloIpyData.GetAttrIDList() + attrValueList = haloIpyData.GetAttrValueList() + # 每个国家最多仅生效一条属性,不同国家属性可叠加 + for aIndex in range(min(len(attrIDList), len(attrValueList))): + attrID = attrIDList[aIndex] + attrValue = attrValueList[aIndex] + lineupHaloAttrInfo[attrID] = lineupHaloAttrInfo.get(attrID, 0) + attrValue + + # --------------------------- 上面统计好了,下面计算武将最终属性 -------------------------------- + baseAttrFormula = IpyGameDataPY.GetFuncCfg("HeroAttrFormula", 1) + otherAttrFormula = IpyGameDataPY.GetFuncCfg("HeroAttrFormula", 2) + fightPowerFormula = IpyGameDataPY.GetFuncCfg("HeroAttrFormula", 3) + + lvAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_LV) + equipAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_MainEquip) + bookAttrDict = olPlayer.GetCalcAttr(ChConfig.Def_CalcAttr_HeroBook) + + GameWorld.DebugLog(" 国家武将统计=%s" % countryHeroInfo, playerID) + GameWorld.DebugLog(" 羁绊武将统计=%s" % fetterHeroInfo, playerID) + GameWorld.DebugLog(" 武将自身属性=%s" % heroSelfAttrInfo, playerID) + GameWorld.DebugLog(" 武将吞噬属性=%s" % heroStarTalentInfo, playerID) + GameWorld.DebugLog(" 武将突破潜能=%s" % heroBreakAttrInfo, playerID) + GameWorld.DebugLog(" 武将觉醒天赋=%s" % heroAwakeTalentInfo, playerID) + GameWorld.DebugLog(" 武将羁绊属性=%s" % heroFetterAttrInfo, playerID) + GameWorld.DebugLog(" 阵容光环属性=%s" % lineupHaloAttrInfo, playerID) + GameWorld.DebugLog(" 阵容上阵加成=InitAddPer=%s,LVAddPer=%s,BreakLVAddPer=%s,StarAddPer=%s" % (InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer), playerID) + + GameWorld.DebugLog(" 主公等级属性=%s" % lvAttrDict, playerID) + GameWorld.DebugLog(" 主公装备属性=%s" % equipAttrDict, playerID) + GameWorld.DebugLog(" 主公图鉴属性=%s" % bookAttrDict, playerID) + + lineupFightPower = 0 # 阵容总战力 + InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer = InitAddPer / 10000.0, LVAddPer / 10000.0, BreakLVAddPer / 10000.0, StarAddPer / 10000.0 + for heroID, selfAttrDict in heroSelfAttrInfo.items(): + lineupHero = lineup.GetLineupHeroByID(heroID) + if not lineupHero: + continue + lineupHero.heroBatAttrDict = {} + lineupHero.fightPower = 0 + + starTalentAttrDict = heroStarTalentInfo.get(heroID, {}) + breakAttrDict = heroBreakAttrInfo.get(heroID, {}) + awakeTalentAttrDict = heroAwakeTalentInfo.get(heroID, {}) + fetterAttrDict = heroFetterAttrInfo.get(heroID, {}) + + logAttrDict = {} + fightPowerParamDict = {} + for attrID in ChConfig.CalcBattleAttrIDList: + attrPerID = ChConfig.AttrPerDict.get(attrID, 0) # 对应百分比提升的属性ID + + lvValue = lvAttrDict.get(attrID, 0) + equipValue = equipAttrDict.get(attrID, 0) + bookValue = bookAttrDict.get(attrID, 0) + bookPer = bookAttrDict.get(attrPerID, 0) / 10000.0 if attrPerID else 0 + + lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = 0, 0, 0, 0 + if attrID in ChConfig.BaseAttrIDList: + lineupInitAddPer, lineupLVAddPer, lineupBreakLVAddPer, lineupStarAddPer = InitAddPer, LVAddPer, BreakLVAddPer, StarAddPer + + heroSelfValue, heroSelfPer = selfAttrDict.get(attrID, 0), 0 # 武将自身基值 + inheritPer = 1 # 继承比例,默认100% + if attrID in ChConfig.AttrInheritPerDict: + attrInheritPerID = ChConfig.AttrInheritPerDict[attrID] # 继承ID + inheritPer = selfAttrDict.get(attrInheritPerID, 100) # 继承比例从武将自身属性中取 + inheritPer /= 100.0 + + lineupHaloValue, lineupHaloPer = lineupHaloAttrInfo.get(attrID, 0), 0 + fetterValue, fetterPer = fetterAttrDict.get(attrID, 0), 0 + starTalentValue, starTalentPer = starTalentAttrDict.get(attrID, 0), 0 + breakLVValue, breakLVPer = breakAttrDict.get(attrID, 0), 0 + awakeTalentValue, awakeTalentPer = awakeTalentAttrDict.get(attrID, 0), 0 + if attrPerID: + heroSelfPer = selfAttrDict.get(attrPerID, 0) / 10000.0 + lineupHaloPer = lineupHaloAttrInfo.get(attrPerID, 0) / 10000.0 + fetterPer = fetterAttrDict.get(attrPerID, 0) / 10000.0 + starTalentPer = starTalentAttrDict.get(attrPerID, 0) / 10000.0 + breakLVPer = breakAttrDict.get(attrPerID, 0) / 10000.0 + awakeTalentPer = awakeTalentAttrDict.get(attrPerID, 0) / 10000.0 + + # 计算 + attrParamDict = {"lvValue":lvValue, "equipValue":equipValue, "bookValue":bookValue, "bookPer":bookPer, + "lineupInitAddPer":lineupInitAddPer, "lineupLVAddPer":lineupLVAddPer, "lineupBreakLVAddPer":lineupBreakLVAddPer, "lineupStarAddPer":lineupStarAddPer, + "heroSelfValue":heroSelfValue, "heroSelfPer":heroSelfPer, "inheritPer":inheritPer, + "lineupHaloValue":lineupHaloValue, "lineupHaloPer":lineupHaloPer, "fetterValue":fetterValue, "fetterPer":fetterPer, + "starTalentValue":starTalentValue, "starTalentPer":starTalentPer, "breakLVValue":breakLVValue, "breakLVPer":breakLVPer, + "awakeTalentValue":awakeTalentValue, "awakeTalentPer":awakeTalentPer, + } + + if attrID in ChConfig.BaseAttrIDList: + attrValue = FormulaControl.Eval("baseAttrFormula", baseAttrFormula, attrParamDict) + else: + attrValue = FormulaControl.Eval("otherAttrFormula", otherAttrFormula, attrParamDict) + #GameWorld.DebugLog(" attrID=%s,attrValue=%s,attrParamDict=%s" % (attrID, attrValue, attrParamDict)) + lineupHero.heroBatAttrDict[attrID] = attrValue + + attrIpyData = IpyGameDataPY.GetIpyGameData("PlayerAttr", attrID) + attrName = attrIpyData.GetParameter() if attrIpyData else "%s" % attrID + fightPowerParamDict[attrName] = attrValue + if attrValue: + logAttrDict["%s-%s" % (attrID, attrName)] = attrValue + + # 计算战力 + fightPower = FormulaControl.Eval("fightPowerFormula", fightPowerFormula, fightPowerParamDict) + skillFightPower = 0 + for skillID in lineupHero.heroSkillIDList: + skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID) + if not skillData: + continue + skillFightPower += skillData.GetFightPower() + fightPowerTotal = fightPower + skillFightPower + lineupHero.fightPower = fightPowerTotal + lineupFightPower += fightPowerTotal + + GameWorld.DebugLog(" 武将最终战力: heroID=%s,fightPower=%s(%s+%s),%s,skillIDList=%s" + % (heroID, fightPowerTotal, fightPower, skillFightPower, logAttrDict, lineupHero.heroSkillIDList), playerID) + + lineup.fightPower = lineupFightPower + GameWorld.DebugLog(" 阵容最终战力: lineupID=%s,lineupFightPower=%s" % (lineupID, lineupFightPower), playerID) + + # 更新排行榜 + if lineupID != ShareDefine.Lineup_Main: + return + + PlayerControl.SetFightPower(curPlayer, lineupFightPower) + + return -- Gitblit v1.8.0