hxp
2025-08-25 cc2207557c22a88475e28f6a05a416c0fa97e527
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -14,14 +14,10 @@
#"""Version = 2017-07-17 15:00"""
#---------------------------------------------------------------------
import GameWorld
import ChEquip
import SkillShell
import ChConfig
import EffGetSet
import PlayerHorse
import PlayerTeam
import SkillCommon
import MirrorAttack
import GameMap
import FBLogic
import GameWorldProcess
@@ -41,40 +37,18 @@
import ChPyNetSendPack
import NetPackCommon
import DataRecordPack
import CalcNoLineEffect
import CalcLineEffect
import PlayerEquipDecompose
import FormulaControl
import PlayerDienstgrad
import PlayerPrestigeSys
import OpenServerCampaign
import PlayerGodWeapon
import PlayerExpandPackCfgMgr
import PlayerWorldAverageLv
import PlayerActivity
import FBCommon
import PassiveBuffEffMng
import EventReport
import PlayerGatherSoul
import PlayerGatherTheSoul
import PlayerSuccess
import PlayerPet
import PlayerGreatMaster
import ItemControler
import GameFuncComm
import IpyGameDataPY
import PlayerRune
import PyGameData
import PlayerMagicWeapon
import PlayerFeastTravel
import PlayerActTurntable
import GameLogic_SealDemon
import GameLogic_ZhuXianBoss
import GameLogic_CrossDemonKing
import PlayerVip
import PlayerRefineStove
import PlayerFamilyTech
import PlayerFamilyZhenfa
import PlayerCostRebate
import PlayerActLunhuidian
import PlayerActGarbageSorting
@@ -82,26 +56,15 @@
import PlayerTongTianLing
import FunctionNPCCommon
import PlayerGoldInvest
import IPY_PlayerDefine
import CrossRealmPlayer
import CrossPlayerData
import NPCHurtManager
import ChNetSendPack
import PlayerLianTi
import PlayerCoat
import PlayerAssist
import PlayerState
import PlayerDogz
import PlayerFaQi
import PlayerLove
import PlayerGubao
import PlayerShentong
import PlayerCharm
import PlayerOnline
import PlayerTask
import PlayerFace
import PlayerMail
import ChPlayer
import GMShell
import GameObj
import random
@@ -607,7 +570,7 @@
#  @return 返回值无意义
def ClearPyPlayerAction(curPlayer):
    #清除py自定义状态
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_PyPlayerAction, 0)
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_PyPlayerAction, 0)
    return
#---------------------------------------------------------------------
@@ -779,21 +742,6 @@
    curPlayer.Stand()
    
    
    return
#---------------------------------------------------------------------
##玩家播放表情
# @param curPlayer 玩家实例
# @return 返回值无意义
# @remarks 玩家播放表情
def DoPlayerShowPlayerFace(curPlayer, faceType):
    #清空玩家点击
    curPlayer.SetActionObj(None)
    #通知中断战斗对峙
    ExitPlayerConfronting(curPlayer)
    #通知停止移动
    curPlayer.StopMove()
    #通知客户端播放表情
    curPlayer.View_ShowPlayerFace(faceType)
    return
#---------------------------------------------------------------------
@@ -1017,9 +965,6 @@
    #刷新技能剩余时间
    SkillCommon.RefreshAllSkillRemainTime(curPlayer, tick)
    
    #队伍玩家退出地图
    PlayerTeam.TeamPlayerLeaveMap(curPlayer, tick, isDisconnect)
    #退出采集
    NPCCommon.ClearCollectNPC(curPlayer)
@@ -1059,9 +1004,6 @@
        CrossPlayerData.ClearCrossSyncDataCache(curPlayer)
        PyGameData.g_fbBuyBuffTimeDict.pop(playerID, None)
    #清除地图玩家缓存
    PyGameData.g_playerFuncAttrDict.pop(playerID, None)
    PyGameData.g_playerEquipPartAttrDict.pop(playerID, None)
    PyGameData.g_equipChangeClassLVInfo.pop(playerID, None)
    PyGameData.g_playerReqEnterFBEx.pop(playerID, None)
    NPCCommon.ClearPriWoodPile(curPlayer)
    #移除地图缓存的境界难度玩家ID信息
@@ -1284,9 +1226,6 @@
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBLineID, lineID)
        GameWorld.DebugLog("进入副本时,最后一次离开的可返回的副本ID更新!mapID=%s,lineID=%s,Pos(%s,%s)" % (mapID, lineID, posX, posY))
        
    # 离开地图
    PlayerAssist.OnPlayerLeaveMap(curPlayer)
    # 从副本中切图
    if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
        #默认回满血
@@ -1439,21 +1378,12 @@
        
        if not FBLogic.OnEnterFBEvent(curPlayer, mapID, lineID, tick):
            GameWorld.DebugLog("    OnEnterFBEvent False!", curPlayer.GetPlayerID())
            if mapID in [ChConfig.Def_FBMapID_CrossBattlefield]:
                NotifyCode(curPlayer, "GeRen_chenxin_268121")
            else:
                NotifyCode(curPlayer, "SingleEnterDefaul")
            NotifyCode(curPlayer, "SingleEnterDefaul")
            return
        
    # 需要动态分布线路的地图,发送到跨服服务器进行分配
    if mapID in ChConfig.Def_CrossDynamicLineMap:
        extendInfo = {}
        if mapID == ChConfig.Def_FBMapID_CrossDemonKing:
            bossID = GameLogic_CrossDemonKing.GetCurFBLineBOSSID(mapID, lineID)
            if not bossID:
                return
            extendInfo["BossID"] = bossID
        msgDict = {"PlayerID":curPlayer.GetPlayerID(), "MapID":mapID, "FuncLineID":lineID, "LV":curPlayer.GetLV()}
        if extendInfo:
            msgDict.update(extendInfo)
@@ -1488,10 +1418,6 @@
    tick = GameWorld.GetGameWorld().GetTick()
    if CheckMoveToFB(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, tick) != ShareDefine.EntFBAskRet_OK:
        return
#    if mapID == ChConfig.Def_FBMapID_XMZZ:
#        #仙魔之争
#        GameLogic_XMZZ.XMZZStartFight(curPlayer)
#        return
    if posX == 0 and posY == 0:
        ipyEnterPosInfo = FBCommon.GetFBLineEnterPosInfo(mapID, lineID, fbLineIpyData)
        retPos = FBLogic.OnGetFBEnterPos(curPlayer, mapID, lineID, ipyEnterPosInfo, tick)
@@ -1516,26 +1442,7 @@
    if isSendToGameServer or mapID in ChConfig.Def_MapID_SendToGameServer \
        or mapID in ReadChConfig.GetEvalChConfig("MapID_SendToGameServer"):
        extendParamList = []
        if mapID == ChConfig.Def_FBMapID_SealDemon:
            newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine', 1)
            # 新手线路特殊处理,直接进入
            if lineID in newbielineList:
                GameWorld.DebugLog("封魔坛虚拟线路只能通过自定义场景进入挑战!")
                return
            else:
                bossID = GameLogic_SealDemon.CurFBLineBOSSID(lineID)
                extendParamList = [bossID]
        elif mapID == ChConfig.Def_FBMapID_ZhuXianBoss:
            bossID = GameLogic_ZhuXianBoss.CurFBLineBOSSID(lineID)
            extendParamList = [bossID, -1]
            enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % ChConfig.Def_FBMapID_ZhuXianBoss)
            if enterCnt >= FBCommon.GetEnterFBMaxCnt(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss):
                if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ZhuXianBossHelpCnt):
                    extendParamList = [bossID, curPlayer.GetFamilyID()]
        elif mapID == ChConfig.Def_FBMapID_DemonKing:
            bossID = GameLogic_CrossDemonKing.GetCurFBLineBOSSID(mapID, lineID)
            extendParamList = [bossID]
        elif mapID in ChConfig.Def_MapID_LineIDToPropertyID:
        if mapID in ChConfig.Def_MapID_LineIDToPropertyID:
            enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)
            extendParamList = [enterCnt]
        elif mapID in ChConfig.MirrorBattleMapIDList:
@@ -2884,6 +2791,25 @@
    #轮回殿
    PlayerActLunhuidian.AddLunhuidianValue(curPlayer, PlayerActLunhuidian.AwardType_PayMoney, type_Price, price)
    if type_Price == ShareDefine.TYPE_Price_Xiantao:
        # 累加未结算战锤 - 经验
        unXiantaoCntExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntExp)
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntExp, unXiantaoCntExp + price)
        # 累加未结算战锤 - 装备
        unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip)
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip + price)
        # 累加未结算战锤 - 战利品
        chapterID = GetMainLevelNowInfo(curPlayer)[0]
        chapterIpyData = IpyGameDataPY.GetIpyGameData("MainChapter", chapterID)
        if chapterIpyData:
            DailyBootyUpperList = chapterIpyData.GetDailyBootyUpperList()
            for itemID, upperCnt in DailyBootyUpperList:
                if upperCnt <= 0:
                    continue
                if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BootyDropToday % itemID) >= upperCnt:
                    continue
                unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID)
                NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty + price)
        PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, price)
    unitPrice = price if quantity == 1 else int(math.ceil(price * 1.0 / quantity)) # 单价
    #reason_name = "Unknown" if not costType else costType
@@ -3059,7 +2985,8 @@
        msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "MoneyType":priceType, "Value":value, "GiveType":giveType, "AddDataDict":addDataDict}
        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_GiveMoney, msgInfo, [serverGroupID])
        return True
    befMoney = GetMoney(curPlayer, priceType)
    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
        updPlayerGold = GetMoneyReal(curPlayer, priceType) + value
        if updPlayerGold > ChConfig.Def_PlayerTotalMoney_Gold:
@@ -3126,6 +3053,11 @@
            NotifyCode(curPlayer, "GetMoney", [priceType, value])
    __GiveMoneyAfter(curPlayer, priceType, value, giveType, addDataDict)
    
    if befMoney == 0:
        aftMoney = GetMoney(curPlayer, priceType)
        if aftMoney > 0:
            ItemControler.CheckGiveBindMoneyTypeItem(curPlayer, priceType)
    return True
def __GiveMoneyAfter(curPlayer, priceType, value, giveType, addDataDict):
@@ -3278,16 +3210,11 @@
# @return 返回值, 参考经验
# @remarks 获得当前玩家的参考经验
def GetPlayerReExp(curPlayer):
    lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
    if not lvIpyData:
        return 0
    return lvIpyData.GetReExp()
## 获得当前玩家的参考金钱
#  @param curPlayer 玩家实例
#  @return
def GetPlayerReMoney(curPlayer):
    return 0
    #lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
    #if not lvIpyData:
    #    return 0
    #return lvIpyData.GetReExp()
#---------------------------------------------------------------------
##增加玩家的PK值
@@ -3434,10 +3361,7 @@
def GetFabaoAddPoint(curPlayer):
    #法宝额外增加玩家每级获得的灵根点
    mwID = IpyGameDataPY.GetFuncCfg('FabaoAddPoint', 1)
    if not PlayerMagicWeapon.GetIsActiveMagicWeapon(curPlayer, mwID, lv=1):
        return 0
    return IpyGameDataPY.GetFuncCfg('FabaoAddPoint', 2)
    return 0
def DoAddPointOpen(curPlayer):
    '''加点功能开启'''
@@ -3453,204 +3377,6 @@
    
#---------------------------------------------------------------------
## 功能模块战斗力类
#
#  分模块计算战斗力
class ModuleFightPower():
    __AttrName = "%s" # 参数为ChConfig.Def_Calc_AllAttrType_MAX对应所有属性列表索引
    __AttrNameNoline = "Noline_%s" # 参数为ChConfig.Def_Calc_AllAttrType_MAX对应所有属性列表索引
    __NolineAttrList = [ChConfig.TYPE_Calc_AttrSpeed] # 需要记录的非线性战斗属性
    ## 初始化
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 初始化
    def __init__(self, mfpType):
        self.mfpType = mfpType
        self.ClearAttr()
        return
    ## 重置所有属性
    #  @param self 类实例
    #  @return 返回值无意义
    def ClearAttr(self):
        for attrIndex in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            value = 0
            setattr(self, self.__AttrName % attrIndex, value)
        for attrIndex in self.__NolineAttrList:
            setattr(self, self.__AttrNameNoline % attrIndex, 0)
        return
    ## 根据战斗属性列表设置计算战斗力属性
    #  @param self 类实例
    #  @return 返回值无意义
    def SetCalcMFPBattleAttr(self, allAttrList):
        battleAttrDict = allAttrList[ChConfig.CalcAttr_Battle]
        # 设置本模块增加的线性战斗属性,非线性战斗属性增加的在刷属性时累加上去
        for attrIndex, value in battleAttrDict.items():
            self.AddCalcMFPAttr(attrIndex, value)
        # 非线性战斗属性仅设置时记录即可
        battleNolineAttrDict = allAttrList[ChConfig.CalcAttr_BattleNoline]
        for attrIndex, value in battleNolineAttrDict.items():
            if attrIndex in self.__NolineAttrList:
                setattr(self, self.__AttrNameNoline % attrIndex, value)
        return
    ## 设置计算战斗力属性值
    def SetCalcMFPAttr(self, attrIndex, value):
        if 1 <= attrIndex < ChConfig.Def_Calc_AllAttrType_MAX:
            attrName = self.__AttrName % attrIndex
            setattr(self, attrName, value)
        return
    ## 增加计算战斗力属性
    #  @param self 类实例
    #  @param key 计算属性类型
    #  @param value 计算属性数值
    #  @return 返回值无意义
    def AddCalcMFPAttr(self, attrIndex, value):
        # 如果有存在计算战斗力所需的参数key值,则增加上去
        if 1 <= attrIndex < ChConfig.Def_Calc_AllAttrType_MAX:
            attrName = self.__AttrName % attrIndex
            setattr(self, attrName, getattr(self, attrName) + value)
    def GetModuleFightPower(self, fpParam, curPlayer):
        MaxHP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrMaxHP) # 最大血量
        MinAtk = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrATKMin) # 最小攻击
        MaxAtk = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrATKMax) # 最大攻击
        Def = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrDEF) # 物防
        Hit = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrHit) * fpParam.GetCftHit() # 命中值
        Miss = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrMiss) * fpParam.GetCftMiss() # 闪避值
        AtkSpeed = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrAtkSpeed) # 攻击速度(数值非攻击间隔)
        SuperHitRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHitRate) * fpParam.GetCftSuperHitRate() # 暴击率
        SuperHitRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHitRateReduce) * fpParam.GetCftSuperHitRateReduce() # 暴击概率抗性
        SuperHit = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHit) # 暴击伤害固定值
        SuperHitReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHitReduce) # 暴击固定减伤
        LuckyHitRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHitRate) * fpParam.GetCftLuckyHitRate() # 会心一击
        LuckyHitRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHitRateReduce) * fpParam.GetCftLuckyHitRateReduce() # 会心一击概率抗性
        LuckyHit = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHit) # 会心一击伤害固定值
        LuckyHitReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHitReduce) # 会心一击伤害固定减伤
        SkillAtkRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SkillAtkRate) * fpParam.GetCftSkillAtkRate() # 技能攻击比例加成
        SkillAtkRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SkillAtkRateReduce) * fpParam.GetCftSkillAtkRateReduce() # 技能攻击比例减少
        DamagePVP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePVP)  # PVP固定伤害
        DamagePVPReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePVPReduce)  # PVP固定减伤
        DamagePVE = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePVE)  # PVE固定伤害
        HPRestore = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_HPRestorePer) # 自动回复血量,固定值
        DamBackPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamBackPer) * fpParam.GetCftDamBackPer() # 反伤百分比
        SpeedValue = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrSpeed) # 移动速度值
        SpeedPer = 0#getattr(self, self.__AttrNameNoline % ChConfig.TYPE_Calc_AttrSpeed) * fpParam.GetCftSpeedPer() # 移动速度百分比系数
        PetMinAtk = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_PetMinAtk) # 宠物最小攻击
        PetMaxAtk = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_PetMaxAtk) # 宠物最大攻击
        PetDamPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_PetDamPer) # 宠物伤害百分比提升
        IceAtk = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrIceAtk) # 冰攻, 元素攻击
        IceDef = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrIceDef) # 冰防, 元素防御
        IgnoreDefRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_IgnoreDefRate) * fpParam.GetCftIgnoreDefRate() # 无视防御几率
        IgnoreDefRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_IgnoreDefRateReduce) * fpParam.GetCftIgnoreDefRateReduce() # 无视防御概率抗性
        DamChanceDef = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamChanceDef) * fpParam.GetCftDamChanceDef() # 20%的概率抵御伤害比率
        BleedDamage = 0#getattr(self, self.__AttrName % ChConfig.TYPE_Calc_BleedDamage) * fpParam.GetCftBleedDamage() # 流血伤害
        AtkBackHP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AtkBackHPPer) # 攻击回复血量
        FaintRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FaintRate) * fpParam.GetCftFaintRate() # 触发击晕
        FaintDefRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FaintDefRate) * fpParam.GetCftFaintDefRate() # 击晕抵抗
        FinalHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurt) # 最终固定伤害增加
        FinalHurtReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurtReduce) # 最终固定伤害减少
        BossFinalHurtPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_BossFinalHurtPer) * fpParam.GetCftBossFinalHurtPer() # Boss最终伤害万分率
        FinalHurtPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurtPer) * fpParam.GetCftFinalHurtPer() # 最终伤害万分率
        FinalHurtReducePer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurtReducePer) * fpParam.GetCftFinalHurtReducePer() # 最终伤害减少万分率
        DamagePerPVP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePerPVP) * fpParam.GetCftDamagePerPVP() # 伤害输出计算百分比PVP
        DamagePerPVPReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePerPVPReduce) * fpParam.GetCftDamagePerPVPReduce() # 伤害输出计算百分比PVP减少
        JobAHurtAddPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobAHurtAddPer) * fpParam.GetCftJobAHurtAddPer() # 对目标战士伤害加成
        JobBHurtAddPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobBHurtAddPer) * fpParam.GetCftJobBHurtAddPer() # 对目标法师伤害加成
        JobCHurtAddPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobCHurtAddPer) * fpParam.GetCftJobCHurtAddPer() # 对目标弓箭伤害加成
        JobAAtkReducePer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobAAtkReducePer) * fpParam.GetCftJobAAtkReducePer() # 战士攻击伤害减免
        JobBAtkReducePer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobBAtkReducePer) * fpParam.GetCftJobBAtkReducePer() # 法师攻击伤害减免
        JobCAtkReducePer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_JobCAtkReducePer) * fpParam.GetCftJobCAtkReducePer() # 弓箭攻击伤害减免
        AffairSpeedPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AffairSpeedPer) * fpParam.GetCftAffairSpeedPer() # 仙盟事务速度加成
        FamilyBossHurtPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FamilyBossHurtPer) * fpParam.GetCftFamilyBossHurtPer() # 仙盟BOSS伤害加成
        FamilyWarHPPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FamilyWarHPPer) * fpParam.GetCftFamilyWarHPPer() # 仙盟联赛生命加成
        FamilyWarAtkPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FamilyWarAtkPer) * fpParam.GetCftFamilyWarAtkPer() # 仙盟联赛攻击加成
        FamilySitExpPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FamilySitExpPer) * fpParam.GetCftFamilySitExpPer() # 仙盟打坐经验加成
        NormalHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_NormalHurt)
        NormalHurtPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_NormalHurtPer) * fpParam.GetCftNormalHurtPer() # 普通附加伤害加成
        FabaoHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FabaoHurt)
        FabaoHurtPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FabaoHurtPer) * fpParam.GetCftFabaoHurtPer() # 法宝附加伤害加成
        Luck = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_Luck)
        ComboRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ComboRate) # 连击几率
        ComboDamPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ComboDamPer) # 连击伤害
        #MaxProDef = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_MaxProDef) # 最大防护值
        #ProDefAbsorb = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ProDefAbsorb) # 防护值吸收伤害比率
        ProDefPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ProDefHPPer) # 防护转化百分比
        OnlyFinalHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_OnlyFinalHurt) # 额外输出伤害
        PVPAtkBackHP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_PVPAtkBackHP) # PVP攻击回血
        NPCHurtAddPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_NPCHurtAddPer) * fpParam.GetCftNPCHurtAddPer() # 对怪物伤害加成
        #其他需作为公式参数的系数
        AtkSpeedParameter = fpParam.GetCftAtkSpeed()
        LuckyHitParameter = 0#fpParam.GetCftLuckyHit()
        #取总属性的
        SuperHitRateTotal = curPlayer.GetSuperHitRate()
        LuckyHitRateTotal = curPlayer.GetLuckyHitRate()
        job = curPlayer.GetJob()
        diffAttrDict = self.__GetAttrFightPowerParamDiff(job)
        for paramName, diffValue in diffAttrDict.items():
            exec("%s = max(0, %s - %s)" % (paramName, paramName, diffValue))
        #获取策划配置的表格
        FightpowerFormula = IpyGameDataPY.GetFuncCfg("FightpowerFormula")
        totalFightPower = eval(FormulaControl.GetCompileFormula("FightpowerFormula", FightpowerFormula))
        #GameWorld.DebugLog("MfpType=%s,FightPower=%s, %s" % (self.mfpType, totalFightPower, self.GetMFPAttrStr()))
        if totalFightPower > ShareDefine.Def_UpperLimit_DWord:
            GameWorld.ErrLog("模块战力超过数值上限, MfpType=%s,fightPower=%s, %s" % (self.mfpType, totalFightPower, self.GetMFPAttrStr()))
            #totalFightPower = ShareDefine.Def_UpperLimit_DWord 模块战力支持超20亿,日志暂保留用于输出提醒
        return totalFightPower
    def __GetAttrFightPowerParamDiff(self, job):
        ## 战力计算属性参数与实际属性差值
        #角色基础模块某些属性不计算战力
        if self.mfpType != ShareDefine.Def_MFPType_Role:
            return {}
        roleBaseAttrDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 1)
        notFightPowerEffIDNameDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 2)
        if job not in roleBaseAttrDict:
            return {}
        diffAttrDict = {}
        jobBaseAttrDict = roleBaseAttrDict[job]
        for attrID, paramName in notFightPowerEffIDNameDict.items():
            if attrID not in jobBaseAttrDict:
                continue
            diffAttrDict[paramName] = jobBaseAttrDict[attrID]
        return diffAttrDict
    def GetMFPAttrStr(self):
        attrStr = ""
        for attrIndex in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            attrName = self.__AttrName % attrIndex
            attrValue = getattr(self, attrName)
            if attrValue <= 0:
                continue
            attrStr += "%s=%s," % (attrName, attrValue)
        for attrIndex in self.__NolineAttrList:
            attrName = self.__AttrNameNoline % attrIndex
            attrValue = getattr(self, attrName)
            if attrValue <= 0:
                continue
            attrStr += "%s=%s," % (attrName, attrValue)
        return attrStr
###############################################################
#人物控制类
@@ -3659,7 +3385,7 @@
#  人物死亡等逻辑处理
class PlayerControl:
    __Player = None
    __fpTypeObjDict = {}
    #---------------------------------------------------------------------
    ## 初始化
    #  @param self 类实例
@@ -3668,46 +3394,6 @@
    #  @remarks 初始化
    def __init__(self, iPlayer):
        self.__Player = iPlayer
    ## 获取模块战斗力对象
    #  @param self 类实例
    #  @param fpType 战斗力类型
    #  @return 返回战斗力对象
    def GetModuleFightPowerObj(self, fpType):
        fpObj = self.__fpTypeObjDict.get(fpType)
        if not fpObj:
            fpObj = ModuleFightPower(fpType)
            self.__fpTypeObjDict[fpType] = fpObj
        return fpObj
    ## 获取模块战斗力对象
    #  @param self 类实例
    #  @return 返回战斗力对象
    def ResetFightPowerObj(self):
        for obj in self.__fpTypeObjDict.values():
            obj.ClearAttr()
    #---------------------------------------------------------------------
    ## 玩家升级加点加技能 前20级自动加点 20级后 以前是加技能点现改成直接升级后读表加技能
    #  @param self 类实例
    #  @return None
    #  @remarks 玩家升级 加点 2010-05-26 adaws修改 原来有加技能点 现将升级加技能提出
    def __DoLVUPAddPoint(self):
        curPlayer = self.__Player
        if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_AddPoint):
            # 未开启前不可加点,因为DoAddPointOpen会一次性补齐,避免意外情况多加了点数
            return
        curFreePoint = curPlayer.GetFreePoint()
        addPoint = GetLvUp_AddPoint(curPlayer)
        if addPoint != 0:
            setFreePoint = curFreePoint + addPoint
            #NotifyCode(curPlayer, "ObtainAttributeDot", [addPoint])
            DataRecordPack.DR_Freepoint(curPlayer, "LvUP", addPoint)
            curPlayer.SetFreePoint(setFreePoint)
        return
    
    ## 加经验值 
    #  @param self 类实例
@@ -3729,31 +3415,25 @@
            NetPackCommon.SendFakePack(curPlayer, sendPack)
            
        #副本获得经验, 无论获得多少经验均需通知, 有些副本逻辑需要通过获得经验时机处理
        if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
            FBLogic.OnGetExp(curPlayer, finalAddExp, expViewType)
        #if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
        #    FBLogic.OnGetExp(curPlayer, finalAddExp, expViewType)
        return finalAddExp
    
    # 参数 addSkillID 表示因什么技能杀死NPC获得经验
    def __AddExp(self, curPlayer, addExp, expViewType, isSysHint, addSkillID=0, expRateEx=0):
        if addExp == 0:
        if addExp <= 0:
            # 不进入计算
            return addExp, expViewType
        
        #取得人物当前经验
        #curTotalExp = GetPlayerTotalExp(curPlayer)
        curTotalExp = curPlayer.GetExpPoint() * ChConfig.Def_PerPointValue + curPlayer.GetTotalExp()
        maxLV = GetPlayerMaxLV(curPlayer)
        maxLVExpStore = IpyGameDataPY.GetFuncCfg("MaxLVExpStore", 1)
        curTotalExp = GetPlayerTotalExp(curPlayer)
        
        curLV = curPlayer.GetLV()
#        # 检查转生等级
#        if curLV >= nextReinLV and curTotalExp >= maxLVExpStore:
#            self.__NotifyExpFull(curPlayer, "GeRen_liubo_260986")
#            GameWorld.DebugLog("经验已满!需先转生!curLV=%s,reinLV=%s" % (curLV, nextReinLV), curPlayer.GetPlayerID())
#            return 0
        maxLV = GetPlayerMaxLV(curPlayer)
        maxLVExpStore = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 2)
        curLV = curPlayer.GetLV()
        # 检查最大等级,maxLVExpStore -1时不限累计经验上限
        if curLV >= maxLV and curTotalExp >= maxLVExpStore and maxLVExpStore != -1:
            self.__NotifyExpFull(curPlayer, "GeRen_admin_825676")
@@ -3762,91 +3442,28 @@
        
        # 杀怪
        if expViewType == ShareDefine.Def_ViewExpType_KillNPC:
            exp_rate = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TotalExpRate)
            superRate = PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(curPlayer, None, None, ChConfig.TriggerType_AddExpRate)
            if superRate:
                # 龙凤镯 经验
                expViewType = ShareDefine.Def_ViewExpType_KillNPCSuper
            if addSkillID == ChConfig.Def_SkillID_LXHY_AddExpRate:
                addSkill = GameWorld.GetGameData().GetSkillBySkillID(addSkillID)
                hasEffect = SkillCommon.GetSkillEffectByEffectID(addSkill, ChConfig.Def_Skill_Effect_AddExpRate)
                if hasEffect:
                    #烈焰战神 经验
                    superRate += hasEffect.GetEffectValue(0)
                    expViewType = ShareDefine.Def_ViewExpType_LYZS
            exp_rate += superRate
            #exp_rate = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TotalExpRate)
            exp_rate = 10000
        elif expViewType in [ShareDefine.Def_ViewExpType_GameEvent, ShareDefine.Def_ViewExpType_Sit]:
            exp_rate = curPlayer.GetGameEventExpRate()
            exp_rate += GetFamilySitExpPer(curPlayer)
            #exp_rate += GetFamilySitExpPer(curPlayer)
        else:
            exp_rate = max(GameWorld.GetGameWorld().GetExpRate(), ChConfig.Def_MaxRateValue)
        exp_rate += expRateEx
        #输入的经验有可能为long型
        addExp = int(addExp * exp_rate / float(ChConfig.Def_MaxRateValue))
        
        #防沉迷计算
        addExp = PlayerGameWallow.ChangeExpByWallow(curPlayer, addExp)
        #===========================================================================================
        # #特殊地图杀怪经验外层加成
        # if expViewType == ShareDefine.Def_ViewExpType_KillNPC:
        #    #mapID = GameWorld.GetMap().GetMapID()
        #    #if mapID in ChConfig.Def_FBMapID_BZZDAll:
        #    #    nobleVIPOuterRate = ...
        #    #    #nobleVIPAddExp += 0 if not nobleVIPOuterRate else int(addExp * nobleVIPOuterRate / float(ChConfig.Def_MaxRateValue))
        #    #    nobleVIPAddExp += nobleVIPOuterRate
        #
        #    outerExpRate = FBLogic.OnGetOuterExpRate(curPlayer)
        #    if outerExpRate > 0:
        #        addExp = int(addExp * outerExpRate / float(ChConfig.Def_MaxRateValue))
        #===========================================================================================
        # 不可再升级时,增加后的经验不可超过最大可存储经验
        #if curLV >= nextReinLV or curLV >= maxLV:
        if curLV >= maxLV and maxLVExpStore > 0:
            addExp = min(addExp, max(0, maxLVExpStore - curTotalExp))
        if addExp <= 0:
            #无法获得经验
            GameWorld.DebugLog("无法获得经验")
            return 0, expViewType
        
        #addExp = min(addExp, ChConfig.Def_UpperLimit_DWord) # 单次加经验不超过20亿
        #缓存获取的经验值, 用于兑换家族荣誉
        #if curPlayer.GetFamilyID() != 0:
        #    curPlayer.SetPerExp(min(curPlayer.GetPerExp() + addExp, ChConfig.Def_UpperLimit_DWord))
        #人物头顶提示
        #=======================================================================
        # viewExpCnt = min(2, addExp / ChConfig.Def_UpperLimit_DWord) # 最多飘两次20亿的
        # viewExp = addExp % ChConfig.Def_UpperLimit_DWord
        # for _ in range(viewExpCnt):
        #    curPlayer.Notify_GetExpView(ChConfig.Def_UpperLimit_DWord, expViewType)
        # if viewExp:
        #    curPlayer.Notify_GetExpView(viewExp, expViewType)
        #
        # if isSysHint:
        #    # 杀怪附加加成显示
        #    if expViewType == ShareDefine.Def_ViewExpType_KillNPC:
        #        nobleVIPAddExp = int(nobleVIPAddExp / 100.0)
        #        #NotifyCode(curPlayer, "GeRen_liubo_74717", [addExp, nobleVIPAddExp])
        #    elif expViewType in [ShareDefine.Def_ViewExpType_GameEvent,
        #                         ShareDefine.Def_ViewExpType_Sit]:
        #        #小游戏事件特殊提示,打坐获取经验
        #        NotifyCode(curPlayer, "ObtainExperience", [addExp])
        #    elif expViewType == ShareDefine.Def_ViewExpType_MousePos:
        #        #鼠标位置提示获得经验
        #        NotifyCode(curPlayer, "GeRen_admin_887936", [addExp])
        #    else:
        #        #正常信息提示
        #        NotifyCode(curPlayer, "GeRen_lhs_0", [addExp])
        #=======================================================================
        #给人物经验 先设经验后升级
        #SetPlayerTotalExp(curPlayer, curTotalExp + addExp)
        totalExp = curTotalExp + addExp
        curExp = totalExp % ChConfig.Def_PerPointValue
        expPoint = totalExp / ChConfig.Def_PerPointValue
@@ -3855,13 +3472,10 @@
            curPlayer.SetExpPoint(expPoint)
        if curPlayer.GetTotalExp() != curExp:
            curPlayer.SetTotalExp(curExp)
        #GameWorld.Log("玩家 = %s 得到经验 = %s ,当前经验倍率 = %s"%(curPlayer.GetName(), addExp,expRate ))
        #小于转生等级才可升级
        #if curLV < nextReinLV and curLV < maxLV:
        if curLV < maxLV:
            self.PlayerLvUp()
        #添加经验成功
        return addExp, expViewType
    
@@ -3881,29 +3495,22 @@
    def PlayerLvUp(self, handLvUp=False):
        curPlayer = self.__Player
        
        if GameObj.GetHP(curPlayer) <= 0:
            #玩家死亡不可升级
            return
        #if GameObj.GetHP(curPlayer) <= 0:
        #    #玩家死亡不可升级
        #    return
        
        #lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
        lvIpyData = IpyGameDataPY.GetIpyGameData("PlayerLV", curPlayer.GetLV())
        lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
        if not lvIpyData:
            GameWorld.ErrLog("经验表异常  lv= %s" % curPlayer.GetLV())
            return
        #lvUpNeedExp = GetLVUPTotalExpNeed(lvIpyData)
        lvUpNeedExp = lvIpyData.GetExpPoint() * ChConfig.Def_PerPointValue + lvIpyData.GetExp()
        lvUpNeedExp = GetLVUPTotalExpNeed(lvIpyData)
        if lvUpNeedExp <= 0:
            return
        
        #增加经验
        #curTotalExp = GetPlayerTotalExp(curPlayer)
        curTotalExp = curPlayer.GetExpPoint() * ChConfig.Def_PerPointValue + curPlayer.GetTotalExp()
        curTotalExp = GetPlayerTotalExp(curPlayer)
        #未达到升级经验
        if curTotalExp < lvUpNeedExp:
            return
        needSyncTalentPoint = False
        playerNeedDoLVUp = False
        curLV = curPlayer.GetLV()
        maxLV = GetPlayerMaxLV(curPlayer)
@@ -3911,14 +3518,7 @@
        curPlayer.BeginRefreshState()
        #befXP = curPlayer.GetXP()
        befLV = curPlayer.GetLV()
        befFreePoint = curPlayer.GetFreePoint()
        befBaseSTR = curPlayer.GetBaseSTR()
        befBasePNE = curPlayer.GetBasePNE()
        befBasePHY = curPlayer.GetBasePHY()
        befBaseCON = curPlayer.GetBaseCON()
        #升级前的世界等级经验
        #beforeExpRate = PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer)
        #befFreePoint = curPlayer.GetFreePoint()
        
        while curTotalExp >= lvUpNeedExp and curLV < maxLV:
            
@@ -3933,24 +3533,17 @@
                isNotifyServer = False
            
            curPlayer.SetLV(curLV, isNotifyServer)
            EventReport.WriteEvent_level_up(curPlayer)
            #EventReport.WriteEvent_level_up(curPlayer)
                       
            # 记录玩家升级
            DataRecordPack.DR_PlayerUpgrade(curPlayer, curPlayer.GetLV(), GetPlayerTotalExp(curPlayer), lvUpNeedExp)
            DataRecordPack.Cache_FightPowerChangeInfo(curPlayer, ChConfig.PowerDownType_LVUP, {'lv':curLV})
            self.__GiveLVMailAward(curLV)
            self.__DoLVUPAddPoint()  # 升级加点
            #self.__DoLVUPAddPoint()  # 升级加点
            #self.__DoLvUpAddSkill()  # 升级加技能
            
            lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
            # 大师天赋点
            if lvIpyData:
                addTalentPoint = lvIpyData.GetTalentPoint()
                if addTalentPoint:
                    needSyncTalentPoint = True
                    PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, addTalentPoint)
            
            PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_LVUp, 1)
            #---是否继续循环---
            curTotalExp = curTotalExp - lvUpNeedExp
            
@@ -3965,58 +3558,28 @@
        #有升级, 转生时刚好是转生等级会默认+1级
        if playerNeedDoLVUp:
            aftLV = curPlayer.GetLV()
            aftFreePoint = curPlayer.GetFreePoint()
            aftBaseSTR = curPlayer.GetBaseSTR()
            aftBasePNE = curPlayer.GetBasePNE()
            aftBasePHY = curPlayer.GetBasePHY()
            aftBaseCON = curPlayer.GetBaseCON()
            #aftFreePoint = curPlayer.GetFreePoint()
            if aftLV > befLV:
                curPlayer.SetLV(aftLV, False) # 这里不再通知GameServer
                PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_LV, aftLV)
                PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_LVUp, aftLV - befLV)
                PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_LV)
                PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_HeroLV, aftLV)
                PlayerActivity.DoAddActivityByLV(curPlayer, befLV, aftLV)
                
            if aftFreePoint > befFreePoint:
                curPlayer.SetFreePoint(aftFreePoint)
                #NotifyCode(curPlayer, "ObtainAttributeDot", [aftFreePoint - befFreePoint])
            if aftBaseSTR > befBaseSTR:
                curPlayer.SetBaseSTR(aftBaseSTR)
            if aftBasePNE > befBasePNE:
                curPlayer.SetBasePNE(aftBasePNE)
            if aftBasePHY > befBasePHY:
                curPlayer.SetBasePHY(aftBasePHY)
            if aftBaseCON > befBaseCON:
                curPlayer.SetBaseCON(aftBaseCON)
            #if aftFreePoint > befFreePoint:
            #    curPlayer.SetFreePoint(aftFreePoint)
            PlayerGubao.DoGubaoAddFreePoint(curPlayer)
            #===================================================================
            # if curPlayer.GetXP() != befXP:
            #    curPlayer.SetXP(curPlayer.GetXP())
            #===================================================================
            #享受世界等级
            #===================================================================
            #curExpRate = PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer)
            #if beforeExpRate <= 0 and curExpRate > 0:
            #    NotifyCode(curPlayer, "GeRen_liubo_127574")
            
            #===================================================================
            # 天赋点通知
            if needSyncTalentPoint:
                PlayerGreatMaster.Sync_GreatMasterFreeSkillPoint(curPlayer)
            # 升级需要执行的游戏功能处理
            GameFuncComm.DoFuncOpenLogic(curPlayer)
            ChEquip.RefreshPlayerLingQiEquipAttr(curPlayer) # 灵器属性会随等级成长
            if aftLV%10 == 0:
                # 控制下刷新次数
                PlayerPet.CalcPetItemAddPlayerAttr(curPlayer)   # 宠物有随等级变化的技能
            
            self.RefreshPlayerAttrState(billboardFunc=PlayerBillboard.UpdatePlayerLVBillboard)
            #放在功能开启后面
            PlayerWorldAverageLv.UpdatePlayerWorldAverageLv(curPlayer)
            PlayerOnline.CalcRoleBase(curPlayer)
            PlayerOnline.GetOnlinePlayer(curPlayer).RefreshRoleAttr()
            #将血设置为最大
            GameObj.SetHPFull(curPlayer)
            if curPlayer.GetMaxMP() > 0:
                curPlayer.SetMP(curPlayer.GetMaxMP())
            #GameObj.SetHPFull(curPlayer)
            #if curPlayer.GetMaxMP() > 0:
            #    curPlayer.SetMP(curPlayer.GetMaxMP())
            
            FBLogic.OnPlayerLVUp(curPlayer)
            # 记录开服活动冲级数据
@@ -4039,149 +3602,6 @@
        return
    
    #---------------------------------------------------------------------
    def CalcRoleBaseAttr(self, curPlayer):
        # 计算玩家角色基础属性值
        curPlayerID = curPlayer.GetID()
        job = curPlayer.GetJob()
        lvAttrDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAttr%s" % job, 1)
        if not lvAttrDict:
            GameWorld.ErrLog('无此职业等级刷属性配置!job=%s' % (job), curPlayerID)
            return
        allAttrList = [{} for _ in range(4)]
        # 职业初始属性
        roleBaseAttrDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 1)
        if job in roleBaseAttrDict:
            for roleBaseAttrID, value in roleBaseAttrDict[job].items():
                CalcAttrDict_Type(roleBaseAttrID, value, allAttrList)
        #GameWorld.DebugLog("初始加属性: %s" % allAttrList)
        # 等级成长属性
        LV = curPlayer.GetLV()
        for lvAttrID, formula in lvAttrDict.items():
            calcValue = eval(FormulaControl.GetCompileFormula("LVUPAttr%s_%s" % (job, lvAttrID), formula))
            CalcAttrDict_Type(lvAttrID, calcValue, allAttrList)
            #GameWorld.DebugLog("    lvAttrID=%s,calcValue=%s" % (lvAttrID, calcValue))
        #GameWorld.DebugLog("等级加属性: %s" % allAttrList)
        # 属性点属性
        hadRefreshAttr = curPlayer.GetDictByKey(ChConfig.Def_Player_HadRefreshAttr) # 本地图是否刷新过属性
        pointFightPowerEx = 0
        pointValueInfo = {ShareDefine.Def_Effect_Metal:[lambda curObj:GetMetal(curObj), lambda curObj, value:SetMetalQualityLV(curObj, value), lambda curObj:GetMetalQualityLV(curObj)],
                          ShareDefine.Def_Effect_Wood:[lambda curObj:GetWood(curObj), lambda curObj, value:SetWoodQualityLV(curObj, value), lambda curObj:GetWoodQualityLV(curObj)],
                          ShareDefine.Def_Effect_Water:[lambda curObj:GetWater(curObj), lambda curObj, value:SetWaterQualityLV(curObj, value), lambda curObj:GetWaterQualityLV(curObj)],
                          ShareDefine.Def_Effect_Fire:[lambda curObj:GetFire(curObj), lambda curObj, value:SetFireQualityLV(curObj, value), lambda curObj:GetFireQualityLV(curObj)],
                          ShareDefine.Def_Effect_Earth:[lambda curObj:GetEarth(curObj), lambda curObj, value:SetEarthQualityLV(curObj, value), lambda curObj:GetEarthQualityLV(curObj)],
                          }
        hasChange_Qualitylv = False #灵根品级是否有变更
        lingGenQualityAttrList = [{} for _ in range(4)]
        for pointAttrID, pointFuncInfo in pointValueInfo.items():
            pointValue = pointFuncInfo[0](curPlayer)
            befPQLV = pointFuncInfo[2](curPlayer)
            pointFuncInfo[1](curPlayer, 0)
            if not pointValue:
                if 0 != befPQLV:
                    hasChange_Qualitylv = True
                continue
            ipyData = IpyGameDataPY.GetIpyGameData("RolePoint", pointAttrID)
            if not ipyData:
                continue
            # 每点属性
            perPointAddAttrDict = ipyData.GetAddAttrInfoPerPoint() # {"职业":[[每X点,属性ID,值], ...], ..}
            addAttrList = perPointAddAttrDict.get(str(job), [])
            for needPoint, pointAddAttrID, pointAddAttrValue in addAttrList:
                pointAddValueTotal = pointAddAttrValue * (pointValue / needPoint)
                CalcAttrDict_Type(pointAddAttrID, pointAddValueTotal, allAttrList)
                #GameWorld.DebugLog("    属性点(%s)加属性: pointValue=%s,pointAddAttrID=%s,pointAddValueTotal=%s" % (pointAttrID, pointValue, pointAddAttrID, pointAddValueTotal))
            pointFightPowerEx += (ipyData.GetFightPowerPerPoint() * pointValue)
            # 点数品质属性
            curPQLV = 0
            pqIntervalList = ipyData.GetPointQualityIntervalList()
            for pqLV, pqValue in enumerate(pqIntervalList, 1): # 灵根品级从1开始
                if pointValue >= pqValue:
                    curPQLV = pqLV
                else:
                    break
            pointFuncInfo[1](curPlayer, curPQLV)
            if curPQLV != befPQLV:
                hasChange_Qualitylv = True
            if not curPQLV:
                continue
            pqAttrInfoDict = ipyData.GetPointQualityAttrDict().get(str(curPlayer.GetJob()), {})
            for pqAttrID, pqAttrValueList in pqAttrInfoDict.items():
                pqAttrValue = 0 if curPQLV > len(pqAttrValueList) else pqAttrValueList[curPQLV - 1]
                CalcAttrDict_Type(int(pqAttrID), pqAttrValue, lingGenQualityAttrList)
            #GameWorld.DebugLog("        属性点(%s)品阶等级属性: befPQLV=%s,curPQLV=%s,pqAttrInfoDict=%s" % (pointAttrID, befPQLV, curPQLV, pqAttrInfoDict))
        #GameWorld.DebugLog("等级属性点加属性: %s" % allAttrList)
        #GameWorld.DebugLog("灵根品阶等级属性: %s" % lingGenQualityAttrList)
        #GameWorld.DebugLog("灵根点数附加战力: %s" % pointFightPowerEx)
        SetMFPExFightPower(curPlayer, ShareDefine.Def_MFPType_Role, pointFightPowerEx)
        SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_RoleBase, allAttrList)
        SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_LingGenQuailty, lingGenQualityAttrList)
        return hasChange_Qualitylv
    #---------------------------------------------------------------------
    def NotifyAllState(self, playerStateDict):
        curPlayer = self.__Player
        notifySelfList = []
        notifyAllList = []
        notifyAllAttrState = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_NotifyAllAttrState)
        #在此处把所有属性的不同通知给客户端
        for index, value in playerStateDict.items():
            curPlayerState, attrType, notifySelf, notifyAll = EffGetSet.GetValueByEffIndexEx(curPlayer, index)
            if not attrType:
                continue
            if notifyAllAttrState and curPlayerState == value:
                #GameWorld.Log("第%d个,原值%d等于现值%d,不发给客户端"%( index, value, curPlayerState ) )
                continue
            notifyStruct = ChPyNetSendPack.tagRefreshType()
            notifyStruct.RefreshType = attrType
            if attrType in [IPY_PlayerDefine.CDBPlayerRefresh_HP, IPY_PlayerDefine.CDBPlayerRefresh_MaxHP]:
                notifyStruct.Value = curPlayerState % ShareDefine.Def_PerPointValue
                notifyStruct.ValueEx = curPlayerState / ShareDefine.Def_PerPointValue
            else:
                notifyStruct.Value = curPlayerState
            if notifySelf:
                notifySelfList.append(notifyStruct)
            if notifyAll:
                notifyAllList.append(notifyStruct)
        #属性组合包
        #通知自己
        if notifySelfList:
            sendPack = ChPyNetSendPack.tagObjInfoListRefresh()
            sendPack.Clear()
            sendPack.ObjID = curPlayer.GetID()
            sendPack.ObjType = curPlayer.GetGameObjType()
            sendPack.Count = len(notifySelfList)
            sendPack.RefreshType = notifySelfList
            NetPackCommon.SendFakePack(curPlayer, sendPack)
        if len(notifyAllList) != 0:
            #广播周围玩家
            sendPack = ChPyNetSendPack.tagObjInfoListRefresh()
            sendPack.Clear()
            sendPack.ObjID = curPlayer.GetID()
            sendPack.ObjType = curPlayer.GetGameObjType()
            sendPack.Count = len(notifyAllList)
            sendPack.RefreshType = notifyAllList
            PyNotifyAll(curPlayer, sendPack, False, -1)
        if not notifyAllAttrState:
            curPlayer.SetDict(ChConfig.Def_PlayerKey_NotifyAllAttrState, 1)
        return
    
    ## 刷新玩家所有状态
    #  @param self 类实例
@@ -4189,58 +3609,13 @@
    #  @return 返回值无意义
    #  @remarks 刷新玩家所有状态
    def RefreshAllState(self, isSyncBuff=False, billboardFunc=None, isForce=False):
        curPlayer = self.__Player
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("Start RefreshAllState!!!", playerID)
        self.RefreshPlayerActionState()
        self.RefreshPlayerAttrState(billboardFunc, isForce)
        return
    
    ## 重计算并刷新玩家所有状态, 目前只用与切换地图
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 刷新玩家所有状态
    def ReCalcAllState(self):
        curPlayer = self.__Player
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("Start ReCalcAllState!!!", playerID)
        for funcIndex in ChConfig.CalcAttrFuncList:
            ClearCalcAttrListValue(curPlayer, funcIndex)
        #先压入BUFF的效果值及技能战斗力
        self.RefreshAllSkill()
        ChEquip.RefreshPlayerEquipAttribute(curPlayer)
        ChEquip.RefreshPlayerLingQiEquipAttr(curPlayer)
        #SkillShell.RefreshPlayerBuffOnAttrAddEffect(curPlayer)
        PlayerHorse.CalcHorseAttrEx(curPlayer)
        PlayerPrestigeSys.CalcOfficialRankAttr(curPlayer)
        PlayerGodWeapon.CalcGodWeaponAttr(curPlayer)
        PlayerDienstgrad.CalcAllDienstgradAttr(curPlayer)
        PlayerPet.CalcPetItemAddPlayerAttr(curPlayer)
        PlayerRune.RefreshRuneAttr(curPlayer)
        PlayerMagicWeapon.CalcMagicWeaponAttr(curPlayer)
        PlayerSuccess.CalcSuccessAttr(curPlayer)
        PlayerVip.CalcVIPAttr(curPlayer)
        PlayerRefineStove.CalcStoveAttr(curPlayer)
        PlayerFamilyTech.CalcFamilyTechAttr(curPlayer)
        PlayerEquipDecompose.RefreshEDAttr(curPlayer)
        PlayerDogz.RefreshDogzAttr(curPlayer)
        PlayerGatherSoul.RefreshGatherSoulAttr(curPlayer)
        PlayerGatherTheSoul.CalcSoulAttr(curPlayer)
        PlayerCoat.CalcClothesCoatSkinAttr(curPlayer)
        PlayerFaQi.CalcFaQiAttr(curPlayer)
        PlayerLove.CalcLoveAttr(curPlayer)
        PlayerCharm.CalcCharmAttr(curPlayer)
        PlayerLianTi.CalcLianTiAttr(curPlayer)
        PlayerShentong.CalcShentongAttr(curPlayer)
        PlayerFamilyZhenfa.CalcZhenfaAttr(curPlayer)
        PlayerFace.CalcFaceAttr(curPlayer)
        PlayerFace.CalcFacePicAttr(curPlayer)
        self.RefreshAllState(isForce=True)
        GameWorld.DebugLog("End ReCalcAllState!!!", playerID)
        return
    
    
@@ -4255,36 +3630,7 @@
    
    # BUFF层单独刷新属性
    def RefreshPlayerAttrByBuffEx(self):
        curPlayer = self.__Player
        if curPlayer.GetDictByKey(ChConfig.Def_Player_RefreshAttrByBuff) != 1:
            return
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("Start RefreshPlayerAttrByBuffEx!!!", playerID)
        beforeMaxHP = GameObj.GetMaxHP(curPlayer)
        beforeMoveSpeedValue = GetSpeedValue(curPlayer)
        #构建玩家刷新通知客户端字典, 缓存[索引, 数值]
        playerStateDict = {}
        for index in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            playerStateDict.update({index:EffGetSet.GetValueByEffIndex(curPlayer, index)})
        #GameWorld.DebugLog("刷属性前=%s" % playerStateDict, playerID)
        #self.PrintAttr(curPlayer, "ˢ֮ǰ")
        #---------------------------开始计算-------------------------------------
        curPlayer.BeginRefreshState()
        # 恢复功能数值  不能调用函数self.InitPlayerState()
        EffGetSet.RestorePlayerFuncAttr(curPlayer)
        # 6.计算buff属性, buff层级的不算如战斗力
        self.__RefreshBuffAttr()
        # 7.刷完属性后需要处理的逻辑
        self.__DoRefreshAttrAfterLogic(beforeMaxHP, beforeMoveSpeedValue, playerStateDict)
        curPlayer.SetDict(ChConfig.Def_Player_RefreshAttrByBuff, 0)
        GameWorld.DebugLog("End RefreshPlayerAttrByBuffEx!!!", playerID)
        return
    
    #===========================================================================
    # #装备和BUFF 效果的计算移到外层
@@ -4305,15 +3651,6 @@
        if isForce:
            self.RefreshPlayerAttrStateEx()
            
        return
    def PrintAttr(self, curPlayer, mark):
        attrInfo = ""
        for index in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            value = EffGetSet.GetValueByEffIndex(curPlayer, index)
            if value:
                attrInfo = "%s,%s=%s" % (attrInfo, index, value)
        GameWorld.DebugLog("%s AttrInfo=%s" % (mark, attrInfo))
        return
    
    def RefreshPlayerAttrStateEx(self):
@@ -4347,807 +3684,33 @@
                        无buff总属性  = 固定总属性 + 内部百分比加成值 + 交叉百分比加成  + 固定总属性百分比加成   + 技能百分比对固定属性加成  + 技能固定值
                        含buff总属性  = 无buff总属性 * buff百分比加成  +  buff固定值
        '''
        curPlayer = self.__Player
        if curPlayer.GetDictByKey(ChConfig.Def_Player_RefreshAttr) != 1:
            return False
        PlayerGubao.CalcGubaoAttr(curPlayer) # 古宝定位为对贯通所有游戏功能系统的属性玩法,所以每次都重新刷新
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("Start RefreshPlayerAttrStateEx!!!", playerID)
        #beforeAtkInterval = curPlayer.GetAtkInterval()
        beforeMaxHP = GameObj.GetMaxHP(curPlayer)
        beforeMoveSpeedValue = GetSpeedValue(curPlayer)
        beforeMaxProDef = GetMaxProDef(curPlayer)
        #[金木水火土]
        beforePointList = [GetMetal(curPlayer), GetWood(curPlayer), GetWater(curPlayer), GetFire(curPlayer), GetEarth(curPlayer)]
        #构建玩家刷新通知客户端字典, 缓存[索引, 数值]
        playerStateDict = {}
        for index in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            playerStateDict.update({index:EffGetSet.GetValueByEffIndex(curPlayer, index)})
        #GameWorld.DebugLog("刷属性前=%s" % playerStateDict, playerID)
        #self.PrintAttr(curPlayer, "ˢ֮ǰ")
        #---------------------------开始计算-------------------------------------
        curPlayer.BeginRefreshState()
        self.ResetFightPowerObj()
        #self.PrintAttr(curPlayer, "重置后")
        notAttrList = [{} for _ in range(4)]
        # 1.初始化人物各项状态及属性
        self.InitPlayerState()
        #self.PrintAttr(curPlayer, "初始化")
        # 功能属性层级一...
        # 2.计算基础属性
        #    2.1 获取所有功能计算点计算的属性值, 统计基础属性累加
        baseAttrDict = {}
        baseAttrNolineDict = {}
        funcAttrLen = len(ChConfig.CalcAttrFuncList)
        funcAttrInfoList = [[{} for _ in range(4)]] * funcAttrLen
        funcInsidePerAttrList = [{}] * funcAttrLen # 功能内部百分比附加属性
        for funcIndex in ChConfig.CalcAttrFuncList:
            # 基础属性等功能汇总完后统一刷新,因为各功能可能会加属性点数
            if funcIndex in [ChConfig.Def_CalcAttrFunc_RoleBase, ChConfig.Def_CalcAttrFunc_LingGenQuailty]:
                continue
            attrInfo, insidePerAttrDict = GetCalcAttrListValue(curPlayer, funcIndex)[:2]
            if attrInfo == notAttrList and not insidePerAttrDict:
                continue
            GameWorld.DebugLog("功能点属性: %s(%s), %s, 内层百分比附加: %s" % (funcIndex, ChConfig.FuncIndexName.get(funcIndex, ""), attrInfo, insidePerAttrDict), playerID)
            funcAttrInfoList[funcIndex] = attrInfo
            funcInsidePerAttrList[funcIndex] = insidePerAttrDict
            # 不同功能点间的数值累加,需使用支持衰减递增的计算方式
            AddAttrDictValue(baseAttrDict, attrInfo[ChConfig.CalcAttr_Base])
            AddAttrDictValue(baseAttrNolineDict, attrInfo[ChConfig.CalcAttr_BaseNoline])
        #    2.2 将基础属性累加到玩家身上
        if baseAttrDict or baseAttrNolineDict:
            # 因为基础属性会影响战斗属性计算,所以先统计增加基础属性
            GameWorld.DebugLog("功能附加点: baseAttrDict=%s,baseAttrNolineDict=%s" % (baseAttrDict, baseAttrNolineDict), playerID)
            CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, baseAttrDict)
            CalcNoLineEffect.ChangePlayerAttrInNoLineEffectList(curPlayer, baseAttrNolineDict)
        # 功能有加基础属性值,这里再重新刷新一下基础属性, 基础属性会影响战斗属性, 每次都刷新角色基础属性
        hasChange_Qualitylv = self.CalcRoleBaseAttr(curPlayer)
        roleBaseAttrInfo, roleInsidePerAttrDict = GetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_RoleBase)[:2]
        lingGenQualityAttrList, lingGenQualityInsidePerAttrDict = GetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_LingGenQuailty)[:2]
        funcAttrInfoList[ChConfig.Def_CalcAttrFunc_RoleBase] = roleBaseAttrInfo
        funcInsidePerAttrList[ChConfig.Def_CalcAttrFunc_RoleBase] = roleInsidePerAttrDict
        funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LingGenQuailty] =  lingGenQualityAttrList
        funcInsidePerAttrList[ChConfig.Def_CalcAttrFunc_LingGenQuailty] =  lingGenQualityInsidePerAttrDict
        GameWorld.DebugLog("功能点属性: %s(%s), %s, 内层百分比附加: %s"
                           % (ChConfig.Def_CalcAttrFunc_RoleBase, ChConfig.FuncIndexName.get(ChConfig.Def_CalcAttrFunc_RoleBase, ""), roleBaseAttrInfo, roleInsidePerAttrDict), playerID)
        GameWorld.DebugLog("功能点属性: %s(%s), %s, 内层百分比附加: %s"
                           % (ChConfig.Def_CalcAttrFunc_LingGenQuailty, ChConfig.FuncIndexName.get(ChConfig.Def_CalcAttrFunc_LingGenQuailty, ""), lingGenQualityAttrList, lingGenQualityInsidePerAttrDict), playerID)
        #self.PrintAttr(curPlayer, "基础后", playerID)
        # 3.计算战斗属性
        #    3.1 战斗属性层级交叉影响基值数值汇总
        #        基础层级(角色基础属性)
        baseAttrList = AddAttrListValue([funcAttrInfoList[ChConfig.Def_CalcAttrFunc_RoleBase],
                                         funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LingGen],
                                         funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LingGenQuailty],
                                         ])
        #GameWorld.DebugLog("基础层级: %s" % baseAttrList, playerID)
        #        功能点交叉影响非线性层对应属性基值列表
        funcAttrPerInfo = {ChConfig.TYPE_Calc_BaseAtkAddPer:[baseAttrList],
                           ChConfig.TYPE_Calc_BaseMaxHPAddPer:[baseAttrList],
                           ChConfig.TYPE_Calc_BaseDefAddPer:[baseAttrList],
                           ChConfig.TYPE_Calc_BaseHitAddPer:[baseAttrList],
                           ChConfig.TYPE_Calc_BaseMissAddPer:[baseAttrList],
                           ChConfig.TYPE_Calc_FaQiMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi]],
                           ChConfig.TYPE_Calc_FaQiAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi]],
                           ChConfig.TYPE_Calc_FaQiDefPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FaQi]],
                           ChConfig.TYPE_Calc_GodWeaponMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_GodWeapon]],
                           ChConfig.TYPE_Calc_GodWeaponAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_GodWeapon]],
                           ChConfig.TYPE_Calc_StoneMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Stone]],
                           ChConfig.TYPE_Calc_StoneAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Stone]],
                           ChConfig.TYPE_Calc_StoneBasePer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Stone]],
                           ChConfig.TYPE_Calc_RealmBasePer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Prestige]],
                           ChConfig.TYPE_Calc_HorseAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Horse]],
                           ChConfig.TYPE_Calc_HorseMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Horse]],
                           ChConfig.TYPE_Calc_HorseTrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseTarin]],
                           ChConfig.TYPE_Calc_PetTrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_PetTarin]],
                           ChConfig.TYPE_Calc_GuardTrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_GuardTarin]],
                           ChConfig.TYPE_Calc_WingTrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_WingTarin]],
                           ChConfig.TYPE_Calc_PeerlessWeaponTrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_PeerlessWeaponTrain]],
                           ChConfig.TYPE_Calc_PeerlessWeapon2TrainAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_PeerlessWeapon2Train]],
                           ChConfig.TYPE_Calc_LianTiAttrPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LianTi]],
                           ChConfig.TYPE_Calc_HorseSkinMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseSkin], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseStar]],
                           ChConfig.TYPE_Calc_HorseSkinAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseSkin], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseStar]],
                           ChConfig.TYPE_Calc_HorseSkinDefPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseSkin], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_HorseStar]],
                           ChConfig.TYPE_Calc_TitleMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Dienstgrad], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_TitleStar]],
                           ChConfig.TYPE_Calc_TitleAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Dienstgrad], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_TitleStar]],
                           ChConfig.TYPE_Calc_TitleDefPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Dienstgrad], funcAttrInfoList[ChConfig.Def_CalcAttrFunc_TitleStar]],
                           ChConfig.TYPE_Calc_FaceMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Face]],
                           ChConfig.TYPE_Calc_FaceAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Face]],
                           ChConfig.TYPE_Calc_FaceDefPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Face]],
                           ChConfig.TYPE_Calc_FacePicMaxHPPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FacePic]],
                           ChConfig.TYPE_Calc_FacePicAtkPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FacePic]],
                           ChConfig.TYPE_Calc_FacePicDefPer:[funcAttrInfoList[ChConfig.Def_CalcAttrFunc_FacePic]],
                           }
        #    3.2 统计各功能之间非线性属性交叉影响累加
        funcCrossAttrPerInfoDict = {} # 百分比交叉影响所提升的属性值 {功能属性编号:{提升的属性类型:数值, ...}, ...}
        for i, funcAttrList in enumerate(funcAttrInfoList):
            battleNoLineAttrDict = funcAttrList[ChConfig.CalcAttr_BattleNoline] # 暂写死只取战斗非线性的
            if not battleNoLineAttrDict:
                continue
            addAttrDict = {}
            #GameWorld.DebugLog("交叉功能点: i=%s,%s" % (i,battleNoLineAttrDict), playerID)
            for noLineAttrType, addAttrPer in battleNoLineAttrDict.items():
                if noLineAttrType not in funcAttrPerInfo or noLineAttrType not in ChConfig.FuncNoLinearAttrDict:
                    continue
                # 使用的基值目标功能索引
                attrRate = addAttrPer / float(ChConfig.Def_MaxRateValue)
                addAttrTypeList = ChConfig.FuncNoLinearAttrDict[noLineAttrType]
                useFuncAttrList = funcAttrPerInfo[noLineAttrType]
                for attrType in addAttrTypeList:
                    addValue = 0
                    for useAttrList in useFuncAttrList:
                        useAttrDict = useAttrList[ChConfig.CalcAttr_Battle] # 默认增加的是战斗线性
                        # 默认提升的属性在线性战斗属性里
                        if attrType not in useAttrDict:
                            continue
                        baseValue = useAttrDict[attrType] # 只是用到目标功能的基值
                        addValue += int(baseValue * attrRate)
                        #GameWorld.DebugLog("    i=%s,calcID=%s,per=%s,rate=%s,baseValue=%s,attrType=%s,addValue=%s" % (i, noLineAttrType, addAttrPer, attrRate, baseValue, attrType, addValue), playerID)
                    if addValue <= 0:
                        continue
                    addAttrDict[attrType] = addAttrDict.get(attrType, 0) + addValue
            if addAttrDict:
                # 增加的数值统计到百分比属性所属功能点
                # 如符文有个武器攻击百分比增加属性,增加的数值属于符文功能,不属于武器功能点的,只是基值使用了武器攻击
                funcCrossAttrPerInfoDict[i] = addAttrDict # 先都统计完后再累加到对应功能属性里,不然可能会导致功能基值变更
        GameWorld.DebugLog("交叉影响属性: %s" % funcCrossAttrPerInfoDict, playerID)
        #    3.3 统计所有功能固定属性影响累加
        allFixAttrDict = {} # 固定属性层级总属性基值
        for funcIndex, funcAttrList in enumerate(funcAttrInfoList):
            # 技能模块不计入功能固定属性、不计战力
            if funcIndex in ChConfig.CalcAttrFuncSkillList:
                continue
            AddAttrDictValue(allFixAttrDict, funcAttrList[ChConfig.CalcAttr_Battle])
        fixAttrPerAddExDict = {} # 固定总属性百分比影响所提升的属性值 {功能属性编号:{提升的属性类型:数值, ...}, ...}
        for funcIndex, funcAttrList in enumerate(funcAttrInfoList):
            fixAddPerDict = funcAttrList[ChConfig.CalcAttr_BattleNoline]
            if not fixAddPerDict:
                continue
            addValueExDict = {}
            for fixAttrType, addPer in fixAddPerDict.items():
                if fixAttrType not in allFixAttrDict:
                    continue
                curFixValue = allFixAttrDict[fixAttrType]
                addValueEx = int(curFixValue * addPer / 10000.0)
                addValueExDict[fixAttrType] = addValueEx
            fixAttrPerAddExDict[funcIndex] = addValueExDict
        GameWorld.DebugLog("固定属性总和: %s" % allFixAttrDict, playerID)
        GameWorld.DebugLog("固定百分比附加属性: %s" % fixAttrPerAddExDict, playerID)
        # 4. 计算属性及战力, 需在计算buff层之前计算
        curLV = curPlayer.GetLV()
        fpParam = IpyGameDataPY.GetIpyGameData("FightPowerParam", curLV)
        mfpDict = {} # 模块战斗力
        mfpObjDict = {}
        for mfpType, attrFuncIndexList in ChConfig.MFPTypeAttrFuncIndexDict.items():
            mfpAttrList = [{} for _ in range(4)]
            mfpAttrExDict = {}
            for funcIndex in attrFuncIndexList:
                if funcIndex in ChConfig.CalcAttrFuncSkillList:
                    # 技能模块不计入功能固定属性、不计战力
                    continue
                funcAttrList = funcAttrInfoList[funcIndex]
                funcInsidePerAttrDict = funcInsidePerAttrList[funcIndex] # 功能点内部百分比加成属性
                funcCrossPerAttrDict = funcCrossAttrPerInfoDict.get(funcIndex, {}) # 功能点交叉百分比加成属性
                fixPerAttrDict = fixAttrPerAddExDict.get(funcIndex, {}) # 功能总固定属性百分比加成属性
                CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, funcAttrList[ChConfig.CalcAttr_Battle])
                CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, funcInsidePerAttrDict)
                CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, funcCrossPerAttrDict)
                CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, fixPerAttrDict)
                # 不算战力的
                if funcIndex in ChConfig.CalcAttrFuncNoFightPowerList:
                    continue
                mfpAttrList = AddAttrListValue([mfpAttrList, funcAttrList])
                AddAttrDictValue(mfpAttrExDict, funcInsidePerAttrDict)
                AddAttrDictValue(mfpAttrExDict, funcCrossPerAttrDict)
                AddAttrDictValue(mfpAttrExDict, fixPerAttrDict)
            mfpObj = self.GetModuleFightPowerObj(mfpType)
            mfpObj.SetCalcMFPBattleAttr(mfpAttrList)
            for attrIndex, value in mfpAttrExDict.items():
                mfpObj.AddCalcMFPAttr(attrIndex, value)
            mfpObjDict[mfpType] = mfpObj
        # 因为计算战力需要取到总属性,所以等各功能点属性累加完后再计算
        for mfpType, mfpObj in mfpObjDict.items():
            mfpValue = 0 if not fpParam else mfpObj.GetModuleFightPower(fpParam, curPlayer)
            mfpSkill = GetMFPSkillFightPower(curPlayer, mfpObj.mfpType)
            mfpEx = GetMFPExFightPower(curPlayer, mfpType)
            mfpTotal = mfpValue + mfpSkill + mfpEx
            mfpDict[mfpObj.mfpType] = mfpTotal
            if mfpType == ShareDefine.Def_MFPType_Plus:
                OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_Plus, mfpTotal)
            elif mfpType == ShareDefine.Def_MFPType_Horse:
                OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_Horse, mfpTotal)
            elif mfpType == ShareDefine.Def_MFPType_Wash:
                OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_Wash, mfpTotal)
        #GameWorld.DebugLog("整体层级线性属性: %s" % allAttrList, playerID)
        # 5.被动技能附加属性,不算战力
        passiveSkillAttrList = [{} for _ in range(4)]
        SkillShell.CalcPassiveAttr_Effect(curPlayer, passiveSkillAttrList)  # 属性类技能与buff同层
        for funcIndex in ChConfig.CalcAttrFuncSkillList:
            passiveSkillAttrList = AddAttrListValue([passiveSkillAttrList, funcAttrInfoList[funcIndex]])
        GameWorld.DebugLog("无战力被动属性: %s" % passiveSkillAttrList, playerID)
        skillFixAttrExDict = {}
        skillFixAddPerDict = passiveSkillAttrList[ChConfig.CalcAttr_BattleNoline]
        for fixAttrType, addPer in skillFixAddPerDict.items():
            if fixAttrType not in allFixAttrDict:
                continue
            curFixValue = allFixAttrDict[fixAttrType]
            addValueEx = int(curFixValue * addPer / 10000.0)
            skillFixAttrExDict[fixAttrType] = addValueEx
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, passiveSkillAttrList[ChConfig.CalcAttr_Battle])
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, skillFixAttrExDict)
        #特殊指定属性公式
        GameMap.SpecialMapSetAttrValueByFormat(curPlayer)
        #护盾值刷新
        self.__RefreshMaxProDef(beforeMaxProDef)
        # 【到此所有功能属性都已刷新处理完毕,复制一份 功能属性的刷新结果,用于BUFF属性单独刷新】
        EffGetSet.CopyPlayerFuncAttr(curPlayer)
        # 6.计算buff属性, buff层级的不算如战斗力
        self.__RefreshBuffAttr()
        # 7.刷完属性后需要处理的逻辑
        self.__DoRefreshAttrAfterLogic(beforeMaxHP, beforeMoveSpeedValue, playerStateDict)
        #通知基础属性
        self.__SyncBaseAttr(curPlayer, baseAttrList)
        #五行灵根变更需要处理的逻辑
        afterPointList = [GetMetal(curPlayer), GetWood(curPlayer), GetWater(curPlayer), GetFire(curPlayer), GetEarth(curPlayer)]
        if beforePointList != afterPointList:
            diffPointAttrList = []
            for i, attrID in enumerate([ShareDefine.Def_Effect_Metal, ShareDefine.Def_Effect_Wood, ShareDefine.Def_Effect_Water,
                           ShareDefine.Def_Effect_Fire, ShareDefine.Def_Effect_Earth]):
                if beforePointList[i] != afterPointList[i]:
                    diffPointAttrList.append(attrID)
            SkillShell.RefreshElementSkillByAttr(curPlayer, diffPointAttrList)
#        if hasChange_Qualitylv:
#            #灵根品级变化处理
#            ChEquip.ChangeEquipfacadeByLingGen(curPlayer)
        # 更新开服活动灵根数据
        OpenServerCampaign.UpdOpenServerCampaignLingGenData(curPlayer)
        # 同步前端战力,因为有 SetFightPower 所以累加战力放在这里所有刷新及计算处理完后才处理,才能正常触发set同步前端
        self.SendModuleFightPowerPack(curPlayer, mfpDict)
        billFuncCnt = len(PyGameData.g_refreshAttrBillboardFunc) # 只处理固定次数,防止死循环
        while billFuncCnt > 0 and PyGameData.g_refreshAttrBillboardFunc:
            billFuncCnt -= 1
            billboardFunc = PyGameData.g_refreshAttrBillboardFunc.pop(0)
            GameWorld.DebugLog("回调排行榜: %s" % billboardFunc, playerID)
            billboardFunc(curPlayer, isForceUpdate=True)
        # 暂停刷新属性标志,必须被调用
        curPlayer.SetDict(ChConfig.Def_Player_RefreshAttr, 0)
        curPlayer.SetDict(ChConfig.Def_Player_RefreshAttrByBuff, 0)
        curPlayer.SetDict(ChConfig.Def_Player_HadRefreshAttr, 1)
        GameWorld.DebugLog("End RefreshPlayerAttrStateEx!!!", playerID)
        return True
    # 生命转化为防护值
    def __RefreshMaxProDef(self, beforeMaxProDef):
        curPlayer = self.__Player
        if GetProDefHPPer(curPlayer) == 0:
            return
        maxHP = GameObj.GetMaxHP(curPlayer)
        proDefPer = GetProDefHPPer(curPlayer)
        #获取策划配置的表格
        GodWeapon4 = IpyGameDataPY.GetFuncCfg("GodWeapon4", 2)
        maxProDef = eval(FormulaControl.GetCompileFormula("GodWeapon4", GodWeapon4))
        SetMaxProDef(curPlayer, int(maxProDef))
        afterMaxProDef = GetMaxProDef(curPlayer)
        addValue = max(0, afterMaxProDef - beforeMaxProDef)
        curProDef = GetProDef(curPlayer)
        if beforeMaxProDef > 0 and addValue > 0 and curPlayer.GetPlayerAction() != IPY_GameWorld.paDie:
            # 同步增加 (死亡状态下不刷)
            SetProDef(curPlayer, min(curProDef + addValue, afterMaxProDef))
        elif curProDef > afterMaxProDef:
            # 做一次防范纠正
            SetProDef(curPlayer, min(curProDef, afterMaxProDef))
        return
    def __RefreshBuffAttr(self):
        ## 刷新buff层属性,该层属性只会改变玩家最终属性,不会影响战力等
        curPlayer = self.__Player
        playerID = curPlayer.GetPlayerID()
        allAttrListBuffs = [{} for _ in range(4)]
        # 6.计算buff属性, buff层级的不算如战斗力
        #        算战斗力总值时该层影响的数值不统计,但刷属性时需计算
        SkillShell.CalcBuffers_Effect(curPlayer, allAttrListBuffs)
        #        层非线性战斗属性累加
        battleNolineAttrBuff = allAttrListBuffs[ChConfig.CalcAttr_BattleNoline]
        CalcNoLineEffect.AddPlayerMapAttrNolineEffect(curPlayer, battleNolineAttrBuff)
        CalcNoLineEffect.ChangePlayerAttrInNoLineEffectList(curPlayer, battleNolineAttrBuff, isBuffAttr=True)
        battleAttrBuff = allAttrListBuffs[ChConfig.CalcAttr_Battle]
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, battleAttrBuff, isBuffAttr=True)
        #        速度特殊处理 计算一次
        self.__RefreshMoveSpeed(allAttrListBuffs)
        # GM测试属性特殊逻辑
        self.__DoRefreshGMAttr()
        #        刷新攻击速度
        self.__SetAtkInterval()
        GameWorld.DebugLog("Buff层属性: %s" % allAttrListBuffs, playerID)
        return
    def __DoRefreshGMAttr(self):
        ## 刷新GM测试属性
        curPlayer = self.__Player
        platform = GameWorld.GetPlatform()
        if platform not in GMShell.TestPlatformList:
            return
        if curPlayer.GetGMLevel() != ChConfig.Def_GM_LV_God:
            return
        ipyDataMgr = IpyGameDataPY.IPY_Data()
        if not ipyDataMgr.GetGMAttrCount():
            return
        playerAccID = GameWorld.GetPlatformAccID(curPlayer.GetAccID())
        gmIpyData = None
        commIpyData = None
        for i in xrange(ipyDataMgr.GetGMAttrCount()):
            ipyData = ipyDataMgr.GetGMAttrByIndex(i)
            if not ipyData.GetIsValid():
                continue
            gmMaxLV = ipyData.GetGMMaxLV()
            if curPlayer.GetLV() > gmMaxLV:
                continue
            gmAccID = ipyData.GetGMAccID()
            if gmAccID == playerAccID:
                gmIpyData = ipyData
                break
            if not gmAccID and not commIpyData:
                commIpyData = ipyData
        if not gmIpyData:
            if not commIpyData:
                return
            gmIpyData = commIpyData
        setAttrDict = {}
        specAttrDict = gmIpyData.GetAttrSpecDict()
        attrLV = gmIpyData.GetAttrLV()
        attrPer = gmIpyData.GetAttrPer()
        if attrLV:
            if attrLV == 1:
                attrLV = curPlayer.GetLV()
            lvIpyData = GetPlayerLVIpyData(attrLV)
            if lvIpyData:
                setAttrDict[ChConfig.AttrName_MaxHP] = int(lvIpyData.GetReMaxHP() * attrPer) # 最大生命值
                setAttrDict[ChConfig.AttrName_Atk] = int(lvIpyData.GetReAtk() * attrPer) # 攻击(最小、最大攻击)
                setAttrDict[ChConfig.AttrName_Def] = int(lvIpyData.GetReDef() * attrPer) # 防御
                setAttrDict[ChConfig.AttrName_Hit] = int(lvIpyData.GetReHit() * attrPer) # 命中
                setAttrDict[ChConfig.AttrName_DefRate] = int(lvIpyData.GetReMiss() * attrPer) # 闪避
                setAttrDict[ChConfig.AttrName_AtkSpeed] = int((lvIpyData.GetReAtkSpeed() + 10000) * attrPer) # 攻击速度, 策划等级表配置的是附加值,所以这里要加
                setAttrDict[ChConfig.AttrName_SkillAtkRate] = int(max(0, lvIpyData.GetReSkillAtkRate() - 10000) * attrPer) # 技能伤害比例, 策划等级表配置的是最终值,初始值是0,所以这里要减
                setAttrDict[ChConfig.AttrName_DamagePVP] = int(lvIpyData.GetReDamagePer() * attrPer) # PVP固定伤害
                setAttrDict[ChConfig.AttrName_DamagePVPReduce] = int(lvIpyData.GetReDamReduce() * attrPer) # PVP固定减伤
                setAttrDict[ChConfig.AttrName_IgnoreDefRate] = int(lvIpyData.GetReIgnoreDefRate() * attrPer) # 无视防御比例
                setAttrDict[ChConfig.AttrName_LuckyHitRate] = int(lvIpyData.GetReLuckyHitRate() * attrPer) # 会心一击率
                setAttrDict[ChConfig.AttrName_LuckyHit] = int(lvIpyData.GetReLuckyHit() * attrPer) # 会心一击伤害
                setAttrDict[ChConfig.AttrName_BleedDamage] = int(lvIpyData.GetReBleedDamage() * attrPer) # 流血伤害增加
                setAttrDict[ChConfig.AttrName_IceAtk] = int(lvIpyData.GetReIceAtk() * attrPer) # 真实伤害
                setAttrDict[ChConfig.AttrName_IceDef] = int(lvIpyData.GetReIceDef() * attrPer) # 真实抵御
                setAttrDict[ChConfig.AttrName_PetAtk] = int(lvIpyData.GetRePetAtk() * attrPer) # 灵宠攻击
                setAttrDict[ChConfig.AttrName_PetSkillAtkRate] = int(max(0, lvIpyData.GetRePetSkillAtkRate() - 10000) * attrPer) # 灵宠技能, 策划等级表配置的是最终值,初始值是0,所以这里要减
                setAttrDict[ChConfig.AttrName_PetDamPer] = int(lvIpyData.GetRePetDamPer() * attrPer) # 灵宠伤害增加
                setAttrDict[ChConfig.AttrName_FinalHurt] = int(lvIpyData.GetReFinalHurt() * attrPer) # 固定伤害增加
                setAttrDict[ChConfig.AttrName_FinalHurtReduce] = int(lvIpyData.GetReFinalHurtReduce() * attrPer) # 固定伤害减少
        # 特殊属性的直接优先级最高,直接覆盖
        for attrType, attrValue in specAttrDict.items():
            setAttrDict[attrType] = attrValue
        gmAttrSetInfo = [{} for _ in range(4)]
        for attrType, attrValue in setAttrDict.items():
            if not attrValue:
                setAttrDict.pop(attrType)
                continue
            CalcAttrDict_Type(attrType, attrValue, gmAttrSetInfo)
        # 直接设置的属性
        if gmAttrSetInfo:
            for key, value in gmAttrSetInfo[ChConfig.CalcAttr_Battle].items():
                EffGetSet.SetValueByEffIndex(curPlayer, key, value)
        # 附加属性
        attrExDict = gmIpyData.GetAttrExDict()
        gmAttrExInfo = [{} for _ in range(4)]
        for attrType, attrValue in attrExDict.items():
            CalcAttrDict_Type(attrType, attrValue, gmAttrExInfo)
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, gmAttrExInfo[ChConfig.CalcAttr_Battle])
        GameWorld.DebugLog("GM测试设置属性: GMAttrID=%s,playerAccID=%s" % (gmIpyData.GetGMAttrID(), playerAccID))
        GameWorld.DebugLog("    GM等级属性: GMAttrLV=%s,attrPer=%s,setAttrDict=%s,specAttrDict=%s,%s"
                           % (attrLV, attrPer, setAttrDict, specAttrDict, gmAttrSetInfo))
        GameWorld.DebugLog("    GM附加属性: attrExDict=%s,%s" % (attrExDict, gmAttrExInfo))
        return
    def __DoRefreshAttrAfterLogic(self, beforeMaxHP, beforeMoveSpeedValue, playerStateDict):
        '''刷完总属性(功能属性 + buff属性) 后需要处理的逻辑
            包含一些数值纠正、属性变更通知等
            @attention: 此函数为刷 功能属性 及 buff属性 通用逻辑,所以不是受buff影响的相关处理请不要放这里,比如战斗力等
        '''
        curPlayer = self.__Player
        #------------------------------计算完毕--------------------------------
        afterMaxHP = GameObj.GetMaxHP(curPlayer)
        addMaxHP = max(0, afterMaxHP - beforeMaxHP)
        if beforeMaxHP > 0 and addMaxHP > 0 and curPlayer.GetPlayerAction() != IPY_GameWorld.paDie:
            # 最大血量增加时,同步增加等量的当前血量 (死亡状态下不刷当前血量)
            GameObj.SetHP(curPlayer, min(GameObj.GetHP(curPlayer) + addMaxHP, afterMaxHP))
        #self.PrintAttr(curPlayer, "最终的")
        curPlayer.EndRefreshState() # 统一在刷属性结束逻辑中调用
        #---------------------------------------------------------------------
        #把属性合并通知
        self.NotifyAllState(playerStateDict)
        #移动速度不同则通知给客户端, 功能层处理的是 SpeedNotBuff , 通知客户端的需要是最终的 SpeedValue
        if beforeMoveSpeedValue != GetSpeedValue(curPlayer):
            SetSpeedValue(curPlayer, GetSpeedValue(curPlayer))
        #纠正当前血魔量不超过最大值
        self.__RestoreHPMP()
        #通知客户端玩家当前经验倍率
        Sync_ExpRateChange(curPlayer)
        return
    def __SyncBaseAttr(self, curPlayer, baseAttrList):
        baseBattleAttrDict = baseAttrList[ChConfig.CalcAttr_Battle]
        attrTypeKeyDict = {ChConfig.TYPE_Calc_AttrATKMin:[ChConfig.Def_PlayerKey_BaseAtkMin, ShareDefine.CDBPlayerRefresh_BaseAtkMin],
                           ChConfig.TYPE_Calc_AttrATKMax:[ChConfig.Def_PlayerKey_BaseAtkMax, ShareDefine.CDBPlayerRefresh_BaseAtkMax],
                           ChConfig.TYPE_Calc_AttrMaxHP:[ChConfig.Def_PlayerKey_BaseMaxHP, ShareDefine.CDBPlayerRefresh_BaseMaxHP],
                           ChConfig.TYPE_Calc_AttrDEF:[ChConfig.Def_PlayerKey_BaseDef, ShareDefine.CDBPlayerRefresh_BaseDef],
                           ChConfig.TYPE_Calc_AttrHit:[ChConfig.Def_PlayerKey_BaseHit, ShareDefine.CDBPlayerRefresh_BaseHit],
                           ChConfig.TYPE_Calc_AttrMiss:[ChConfig.Def_PlayerKey_BaseMiss, ShareDefine.CDBPlayerRefresh_BaseMiss],
                           }
        notifySList = []
        for attrType, attrInfo in attrTypeKeyDict.items():
            attrKey, refreshType = attrInfo
            baseValue = baseBattleAttrDict.get(attrType, 0)
            curBaseValue = curPlayer.GetDictByKey(attrKey)
            if baseValue != curBaseValue:
                curPlayer.SetDict(attrKey, baseValue)
                notifyStruct = ChPyNetSendPack.tagRefreshType()
                notifyStruct.RefreshType = refreshType
                notifyStruct.Value = baseValue
                notifySList.append(notifyStruct)
        # 通知基础属性
        if notifySList:
            sendPack = ChPyNetSendPack.tagObjInfoListRefresh()
            sendPack.Clear()
            sendPack.ObjID = curPlayer.GetID()
            sendPack.ObjType = curPlayer.GetGameObjType()
            sendPack.Count = len(notifySList)
            sendPack.RefreshType = notifySList
            NetPackCommon.SendFakePack(curPlayer, sendPack)
        return
    #---------------------------------------------------------------------
    
    ## 刷新玩家技能战斗力
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 刷新玩家被动技能Buff
    def RefreshAllSkill(self):
        curPlayer = self.__Player
        skillManager = curPlayer.GetSkillManager()
        # 重置模块技能战斗力
        for mfpType in ShareDefine.ModuleFightPowerTypeList:
            SetMFPSkillFightPower(curPlayer, mfpType, 0)
        for i in range(0, skillManager.GetSkillCount()):
            curSkill = skillManager.GetSkillByIndex(i)
            mfpType = ChConfig.Def_SkillFuncType_MFPType.get(curSkill.GetFuncType(), ShareDefine.Def_MFPType_Role)
            skillMFP = GetMFPSkillFightPower(curPlayer, mfpType)
            SetMFPSkillFightPower(curPlayer, mfpType, skillMFP + curSkill.GetFightPower())
        return
    
    ## 技能升级刷属性战斗力处理
    def RefreshSkillFightPowerEx(self, skillID, beforeFightPower, isRefreshState=True):
        curPlayer = self.__Player
        # 新技能战力-旧技能战力为增加的技能战力
        curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)
        if not curSkill:
            return
        mfpType = ChConfig.Def_SkillFuncType_MFPType.get(curSkill.GetFuncType(), ShareDefine.Def_MFPType_Role)
        addFightPower = curSkill.GetFightPower() - beforeFightPower
        skillMFP = GetMFPSkillFightPower(curPlayer, mfpType)
        SetMFPSkillFightPower(curPlayer, mfpType, max(0, skillMFP + addFightPower))
        GameWorld.DebugLog("刷新技能附加战斗力: skillID=%s,beforeFightPower=%s,mfpType=%s,skillMFP=%s,updMFP=%s"
                           % (skillID, beforeFightPower, mfpType, skillMFP, skillMFP + addFightPower), curPlayer.GetPlayerID())
        if isRefreshState:
            # 如果需要同步排行榜的话先强制刷属性
            self.RefreshPlayerAttrState()
        return
    
    def RefreshSkillFightPowerByDel(self, delSkillID, isRefreshState=True):
        curPlayer = self.__Player
        # 新技能战力-旧技能战力为增加的技能战力
        curSkill = GameWorld.GetGameData().GetSkillBySkillID(delSkillID)
        if not curSkill:
            return
        delFightPower = curSkill.GetFightPower()
        mfpType = ChConfig.Def_SkillFuncType_MFPType.get(curSkill.GetFuncType(), ShareDefine.Def_MFPType_Role)
        skillMFP = GetMFPSkillFightPower(curPlayer, mfpType)
        SetMFPSkillFightPower(curPlayer, mfpType, max(0, skillMFP - delFightPower))
        GameWorld.DebugLog("刷新技能附加战斗力: delSkillID=%s,mfpType=%s,skillMFP=%s,delFightPower=%s"
                           % (delSkillID, mfpType, skillMFP, delFightPower), curPlayer.GetPlayerID())
        if isRefreshState:
            # 如果需要同步排行榜的话先强制刷属性
            self.RefreshPlayerAttrState()
        return
    
    ## 计算被动buff属性加成
    #  @param self 类实例
    #  @return 
    def CalcPassiveBuffAttr(self):
        #=======================================================================
        # curPlayer = self.__Player
        # allAttrListPassive = [{} for i in range(4)]
        # SkillShell.CalcCurBuffer_Effect(curPlayer.GetPassiveBuf(), curPlayer, allAttrListPassive)
        # SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PassiveBuf, allAttrListPassive)
        #=======================================================================
        return
    ## //A3 A1 各功能模块战斗力信息 #tagMCModuleFightPowerInfo
    #  @param curPlayer 玩家
    #  @return None
    def SendModuleFightPowerPack(self, curPlayer, mfpDict):
        mfpDataList = []
        totalFightPower = 0
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("战力功能点: %s" % ChConfig.MFPTypeAttrFuncIndexDict, playerID)
        GameWorld.DebugLog("模块战力: %s" % mfpDict, playerID)
        for mfpType, fightPower in mfpDict.items():
            SetMFPFightPower(curPlayer, mfpType, fightPower)
            mfpData = ChPyNetSendPack.tagMCModuleFightPower()
            mfpData.Clear()
            mfpData.MfpType = mfpType
            mfpData.FightPower = fightPower % ChConfig.Def_PerPointValue # 当前模块战斗力数值
            mfpData.FightPowerEx = fightPower / ChConfig.Def_PerPointValue # 当前模块战斗力数值
            mfpDataList.append(mfpData)
            totalFightPower += fightPower # 累加总战斗力
        # //A3 A1 各功能模块战斗力信息 #tagMCModuleFightPowerInfo
        mfpInfo = ChPyNetSendPack.tagMCModuleFightPowerInfo()
        mfpInfo.Clear()
        mfpInfo.TotalFightPower = totalFightPower % ChConfig.Def_PerPointValue
        mfpInfo.TotalFightPoweEx = totalFightPower / ChConfig.Def_PerPointValue
        mfpInfo.MFPCnt = len(mfpDataList)
        mfpInfo.MFPList = mfpDataList
        NetPackCommon.SendFakePack(curPlayer, mfpInfo)
        beforeFightPower = GetFightPower(curPlayer)
        SetFightPower(curPlayer, totalFightPower)
        if totalFightPower < beforeFightPower:
            DataRecordPack.DR_FightPowerChangeInfo(curPlayer, beforeFightPower)
        highestFightPower = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_Highest, 0,
                                                           ChConfig.Def_PDictType_FightPower)
        highestFightPower += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_HighestEx, 0,
                                                            ChConfig.Def_PDictType_FightPower) * ChConfig.Def_PerPointValue
        if totalFightPower > highestFightPower:
            highestFightPower = totalFightPower
            NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Highest, highestFightPower % ChConfig.Def_PerPointValue,
                                 ChConfig.Def_PDictType_FightPower)
            NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_HighestEx, highestFightPower / ChConfig.Def_PerPointValue,
                                 ChConfig.Def_PDictType_FightPower)
        GameWorld.DebugLog("总战力: %s, 历史最高战力: %s, beforeFightPower=%s" % (totalFightPower, highestFightPower, beforeFightPower), playerID)
        PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
        # 记录开服活动数据
        OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
        if beforeFightPower != totalFightPower:
            CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
        return
    def __RefreshMoveSpeed(self, allAttrListBuffs):
        ## 刷新移动速度
        curPlayer = self.__Player
        playerID = curPlayer.GetPlayerID()
        moveSpeedFormat = IpyGameDataPY.GetFuncCfg("MoveSpeed")
        speed = GetSpeedNotBuff(curPlayer)
        GameWorld.DebugLog("功能移动速度值: speed=%s" % speed, playerID)
        # 骑乘状态加上骑乘附加速度
        if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
            speedHorse = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SpeedHorse)
            speed += speedHorse
            GameWorld.DebugLog("    骑乘状态附加值: %s, speed=%s" % (speedHorse, speed), playerID)
        buffBattleAttr = allAttrListBuffs[ChConfig.CalcAttr_Battle]
        buffBattleNolineAttr = allAttrListBuffs[ChConfig.CalcAttr_BattleNoline]
        #buff速度加成
        buffSpeed = buffBattleAttr.get(ChConfig.TYPE_Calc_AttrSpeed, 0)
        buffSpeedPer = buffBattleNolineAttr.get(ChConfig.TYPE_Calc_AttrSpeed, 0)
        if buffSpeed or buffSpeedPer:
            speed = int(speed * (ShareDefine.Def_MaxRateValue + buffSpeedPer) / float(ShareDefine.Def_MaxRateValue) + buffSpeed)
            GameWorld.DebugLog("    buff影响后速度值: speed=%s,buffSpeedPer=%s,buffSpeed=%s" % (speed, buffSpeedPer, buffSpeed), playerID)
        speed = max(speed, 0)   #防小于0错误
        if GetSpeedValue(curPlayer) != speed:
            SetSpeedValue(curPlayer, speed)
            moveSpeed = eval(FormulaControl.GetCompileFormula("MoveSpeed", moveSpeedFormat))
            curPlayer.SetSpeed(moveSpeed)
            GameWorld.DebugLog("公式计算后移动频率: moveSpeed=%s 毫秒/格" % moveSpeed, playerID)
            fightPet = curPlayer.GetPetMgr().GetFightPet()
            #无出战宠物
            if fightPet:
                fightPet.SetSpeed(moveSpeed)
        return
    ##刷新攻击间隔
    # @param self 类实例
    # @return None
    def __SetAtkInterval(self):
        curPlayer = self.__Player
        atkSpeed = GetAtkSpeed(curPlayer)
        formula = IpyGameDataPY.GetFuncCfg("AtkInterval")
        atkInterval = 0 if not formula else eval(FormulaControl.GetCompileFormula("AtkInterval", formula))
        curPlayer.SetAtkInterval(atkInterval)
        return
    
    ## 刷新玩家所有行为BUFF状态
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 刷新玩家所有行为BUFF状态
    def RefreshPlayerActionState(self):
        curPlayer = self.__Player
        playerID = curPlayer.GetPlayerID()
        GameWorld.DebugLog("Start RefreshPlayerActionState!!!", playerID)
        #curTime = time.clock()
        #先清除所有状态
        OperControlManager.ClearObjActionState(curPlayer)
        #再根据BUFF 加上状态
        SkillShell.CalcBuffer_ActionState(curPlayer)
    #---------------------------------------------------------------------
    ## 刷新血量和魔
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 刷新血量和魔
    def __RestoreHPMP(self):
        curPlayer = self.__Player
        if not curPlayer.GetInitOK():
            #玩家未初始化成功, 不修正血量和魔法值, 因此时有可能因为某些影响主角的物品未初始化完毕(如宠物装备)
            return
        curPlayerHP = GameObj.GetHP(curPlayer)
        curPlayerMaxHP = GameObj.GetMaxHP(curPlayer)
        #=======================================================================
        # curPlayerMP = curPlayer.GetMP()
        # curPlayerMaxMP = curPlayer.GetMaxMP()
        #=======================================================================
        if curPlayerHP > curPlayerMaxHP:
            GameObj.SetHPFull(curPlayer)
        #=======================================================================
        # if curPlayerMP > curPlayerMaxMP:
        #    curPlayer.SetMP(curPlayerMaxMP)
        #=======================================================================
        return
    #---------------------------------------------------------------------
    ## 初始化玩家基本状态 这里不对( 计算现有战斗属性中的元素进行处理 )
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 初始化玩家基本状态 这里不对( 计算现有战斗属性中的元素进行处理 )
    def InitPlayerState(self):
        curPlayer = self.__Player
        #清空战斗属性 //战斗属性设置数值为0的, 由C++处理 如元素属性,命中等
        curPlayer.ClearBattleEffect()
        initAttrDict = {
                        #ChConfig.TYPE_Calc_AttrCurSTR:curPlayer.GetBaseSTR(),
                        #ChConfig.TYPE_Calc_AttrCurPNE:curPlayer.GetBasePNE(),
                        #ChConfig.TYPE_Calc_AttrCurPHY:curPlayer.GetBasePHY(),
                        #ChConfig.TYPE_Calc_AttrCurCON:curPlayer.GetBaseCON(),
                        #ChConfig.TYPE_Calc_AttrSpeed:curPlayer.GetBaseSpeed(),
                        ChConfig.TYPE_Calc_AttrAtkSpeed:ChConfig.Def_BaseAtkSpeed,
                        ChConfig.TYPE_Calc_AttrFightExpRate:GameWorld.GetGameWorld().GetExpRate(),
                        ChConfig.TYPE_Calc_AttrGameExpRate:GameWorld.GetGameWorld().GetExpRate(),
                        ChConfig.TYPE_Calc_AttrPetExpRate:GameWorld.GetGameWorld().GetExpRate(),
                        ChConfig.TYPE_Calc_HitSucessRate:ChConfig.Def_MaxRateValue,
                        ChConfig.TYPE_Calc_CurePer:ChConfig.Def_MaxRateValue,
                        ChConfig.TYPE_Calc_YinjiTime:IpyGameDataPY.GetFuncCfg('Yinji', 1),  # 每X秒自动消失一个印记
                        }
        for i in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            if i in [ChConfig.TYPE_Calc_AttrHP, ChConfig.TYPE_Calc_AttrMP, ChConfig.TYPE_Calc_ProDef]:
                continue
            value = 0 if i not in initAttrDict else initAttrDict[i]
            EffGetSet.SetValueByEffIndex(curPlayer, i, value)
        #初始化拾取距离
        if curPlayer.GetPickupDist() != ChConfig.Def_RolePickupItemDist:
            curPlayer.SetPickupDist(ChConfig.Def_RolePickupItemDist)
        #玩家初始化可攻击
        if not curPlayer.GetCanAttack():
            curPlayer.SetCanAttack(True)
        #初始化灵根
        SetMetal(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % ShareDefine.Def_Effect_Metal))
        SetWood(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % ShareDefine.Def_Effect_Wood))
        SetWater(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % ShareDefine.Def_Effect_Water))
        SetFire(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % ShareDefine.Def_Effect_Fire))
        SetEarth(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % ShareDefine.Def_Effect_Earth))
        return True
    #---------------------------------------------------------------------
    ## 初始化场景buff
    #  @param self 类实例
    #  @return 返回值无意义
    #  @remarks 初始化场景buff
    def InitMapBuffState(self):
        curPlayer = self.__Player
        #初始化区域, 默认为普通区域
        if GameMap.GetAreaTypeByMapPos(curPlayer.GetPosX(), curPlayer.GetPosY()) != IPY_GameWorld.gatNormal:
            curPlayer.SetAreaType(IPY_GameWorld.gatNormal)
        return
    
    #---------------------------------------------------------------------
@@ -5248,8 +3811,6 @@
        DoPlayerDead(curPlayer)
        
        GameObj.ClearPyPlayerState(curPlayer)
        MirrorAttack.OnPlayerDead(curPlayer)
        return
    
    
@@ -5626,92 +4187,22 @@
#        return False
    
    return True
#------------------------------------------------------------------------------------
##初始化玩家背包.
# @param curPlayer 玩家实例
# @return 返回值无意义
# @remarks 初始化玩家背包
def Init_ItemPack(curPlayer):
    packType = IPY_GameWorld.rptItem
    #初始化玩家背包
    if packType not in ChConfig.Def_Type_CanBuyPack_PlayerDict.keys():
        return
    #获取玩家背包
    curPack = curPlayer.GetItemManager().GetPack(packType)
    #默认14格子 + 开启的
    keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict.get(packType)[ChConfig.Def_PlayerPackDict_Index_Key]
    count = ItemCommon.GetPackInitCount(packType) + curPlayer.NomalDictGetProperty(keyName)
    curPack.SetCount(count)
    #通知客户端背包格子数目
#    curPlayer.Sync_ItemCount(curPack.GetCount())
    curPack.Sync_PackCanUseCount()
    return
#------------------------------------------------------------------------------------
##初始化玩家仓库.
# @param curPlayer 玩家实例
# @return 返回值无意义
# @remarks 初始化玩家仓库
def Init_Warehouse(curPlayer):
    packType = IPY_GameWorld.rptWarehouse
    #初始化玩家背包
    if packType not in ChConfig.Def_Type_CanBuyPack_PlayerDict.keys():
        return
    #获取玩家背包
def Init_PackCount(curPlayer, packType, defaultMax=False, isSync=True):
    ## 初始化刷新玩家某个背包格子数
    curPack = curPlayer.GetItemManager().GetPack(packType)
    #默认42格子 + 开启的
    keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict.get(packType)[ChConfig.Def_PlayerPackDict_Index_Key]
    count = ItemCommon.GetPackInitCount(packType) + curPlayer.NomalDictGetProperty(keyName)
    curPack.SetCount(count)
    #通知客户端
    curPack.Sync_PackCanUseCount()
    return
##初始化寻宝背包
# @param curPlayer 玩家实例
# @return None
def Init_TreasurePack(curPlayer):
    curPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptTreasure)
    curPack.SetCount(ItemCommon.GetPackInitCount(ShareDefine.rptTreasure))
    #通知客户端
    curPack.Sync_PackCanUseCount()
    maxCount = curPack.GetMaxCount()
    if defaultMax:
        curPack.SetCount(maxCount)
    else:
        count = ItemCommon.GetPackInitCount(packType) + ItemCommon.GetPackOpenItemCnt(curPlayer, packType)
        curPack.SetCount(min(count, maxCount))
    if isSync:
        curPack.Sync_PackCanUseCount()
    return
##初始化玩家收纳柜
# @param curPlayer 玩家实例
# @param packType 背包类型
# @return 返回值无意义
def Init_CabinetCountByType(curPlayer, packType):
    keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict.get(packType)[ChConfig.Def_PlayerPackDict_Index_Key]
    if keyName == None:
        GameWorld.ErrLog("Init_Pack Error type=%s" % packType)
        return
    #初始化时装武器背包
    curPack = curPlayer.GetItemManager().GetPack(packType)
    #默认14格子 + 开启的
    count = ChConfig.Def_PackCnt_WeaponCoat + curPlayer.NomalDictGetProperty(keyName)
    curPack.SetCount(count)
    #通知客户端
    curPack.Sync_PackCanUseCount()
    return
#---------------------------------------------------------------------
def IsInOperationAction(curPlayer, actName, actIDKey, crossActName="", crossActIDKey=""):
    ## 玩家是否有正在进行中运营活动,不含参与结束阶段
    
@@ -5756,8 +4247,6 @@
def Sync_ExpRateChange(curPlayer):
    totalExpRate = GetPlayerExpRate(curPlayer)
    fightExpRate = curPlayer.GetFightExpRate() # 系统及功能累加
    fightExpRate += PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer) # 世界等级
    fightExpRate += PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_FightExpRate) # VIP加成
    fightExpRate += PlayerGoldInvest.GetAddFightExpRate(curPlayer)
    
    actExpRateInfo = PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_ExpRate, {})# 多倍经验活动加成
@@ -5813,17 +4302,6 @@
                totalExpRate -= effExpRate
                
    return totalExpRate
##记录玩家失去金钱的流向记录,消息中会记录玩家拥有的金钱信息
# @param curPlayer 玩家实例
# @param moneyType 金钱类型
# @param logIndex 流向记录索引
# @param tagID 在此用于记录特别标识(物品ID)
# @param par 在此用于记录金额
# @param msg 记录特别的信息
# @return None
def DataServerMoneyLog(curPlayer, moneyType, logIndex, tagID=0, par=0, msg=""):
    return
#===============================================================================
#---玩家扩展字段---
@@ -5918,18 +4396,58 @@
        SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ForbidenTalk, 0)
    return
def IsMainLevelPass(curPlayer, lvID):
    ## 判断玩家是否过关某个主线关卡ID
    # @param lvID: 关卡唯一ID,与策划约定好 = 章节*100+关卡编号
    passChapterID, passLevelNum, _ = GetMainLevelPassInfo(curPlayer)
    passValue = passChapterID * 100 + passLevelNum # 因为pass的记录是带波数的,即当前关卡boss还没过关,所以只有大于该记录值的才算过关
    return passValue > lvID
## 主线关卡过关进度值 = 章节*10000+关卡编号*100+第x波
def GetMainLevelPassValue(curPlayer): return curPlayer.GetExAttr1()
def SetMainLevelPassValue(curPlayer, value): curPlayer.SetExAttr1(value, False, False) # 不通知GameServer
def SetMainLevelPassInfo(curPlayer, chapterID, levelNum, wave=0):
    ## 设置主线关卡过关进度
    # @param chapterID: 章节ID
    # @param levelNum: 关卡编号
    # @param wave: 第x波
    value = ComMainLevelValue(chapterID, levelNum, wave)
    SetMainLevelPassValue(curPlayer, value)
    return value
def GetMainLevelPassInfo(curPlayer):
    ## 获取主线关卡过关进度信息
    # @return: chapterID, levelNum, wave
    return GetMainLevelValue(GetMainLevelPassValue(curPlayer))
## 主线关卡当前进度值 = 章节*10000+关卡编号*100+第x波
def GetMainLevelNowValue(curPlayer): return curPlayer.GetExAttr2()
def SetMainLevelNowValue(curPlayer, value): curPlayer.SetExAttr2(value, False, False) # 不通知GameServer
def SetMainLevelNowInfo(curPlayer, chapterID=1, levelNum=1, wave=1):
    ## 设置主线关卡当前进度
    # @param chapterID: 章节ID
    # @param levelNum: 关卡编号
    # @param wave: 第x波
    value = ComMainLevelValue(chapterID, levelNum, wave)
    SetMainLevelNowValue(curPlayer, value)
    return value
def GetMainLevelNowInfo(curPlayer):
    ## 获取主线关卡当前进度信息
    # @return: chapterID, levelNum, wave
    return GetMainLevelValue(GetMainLevelNowValue(curPlayer))
def ComMainLevelValue(chapterID, levelNum, wave=0): return chapterID * 10000 + levelNum * 100 + wave
def GetMainLevelValue(value):
    chapterID = value / 10000
    levelNum = value % 10000 / 100
    wave = value % 100
    return chapterID, levelNum, wave
## 协助目标玩家ID
def SetAssistTagPlayerID(curPlayer, value):
    curPlayer.SetExAttr1(value, True, False) # 不通知GameServer
    NPCHurtManager.OnSetAssistTagPlayerID(curPlayer, value)
    return
def GetAssistTagPlayerID(curPlayer): return curPlayer.GetExAttr1()
def GetAssistTagPlayerID(curPlayer): return 0
## 队伍相关审核开关状态, joinReqCheck-入队申请是否需要审核; inviteCheck-组队邀请是否需要审核;
def SetTeamCheckStateEx(curPlayer, joinReqCheck, inviteCheck): return SetTeamCheckState(curPlayer, joinReqCheck * 10 + inviteCheck)
def SetTeamCheckState(curPlayer, checkState): return curPlayer.SetExAttr2(checkState, False, True)
def GetTeamCheckState(curPlayer): return curPlayer.GetExAttr2()
def SetTeamCheckState(curPlayer, checkState): return
## 副本功能线路ID, 这里做db存储,防止在合并地图副本中掉线重上时前端无法加载正确的场景资源,登录加载场景时机为0102包
def SetFBFuncLineID(curPlayer, mapID, funcLineID):
    value = mapID * 1000 + funcLineID
@@ -5973,8 +4491,8 @@
def SetVIPExpireTime(curPlayer, expireTime): return
##最近一次提升VIP等级时间
def GetVIPLVUpTime(curPlayer): return curPlayer.GetExAttr9()
def SetVIPLVUpTime(curPlayer, lvUpTime): return curPlayer.SetExAttr9(lvUpTime, False, True)
def GetVIPLVUpTime(curPlayer): return 0
def SetVIPLVUpTime(curPlayer, lvUpTime): return
##聊天气泡框
def GetChatBubbleBox(curPlayer): return curPlayer.GetExAttr10()
@@ -6035,69 +4553,16 @@
        GameWorld.DebugLog("更新玩家所属服务器组ID: serverGroupID=%s" % serverGroupID)
    return
##影响外观的3部位索引记录 123456789  123:武器格子索引 456:副手  789:衣服
def GetFaceEquipIndexList(curPlayer):
    attr15 = curPlayer.GetExAttr15()
    return [attr15%1000, attr15/1000%1000, attr15/1000000]
def SetFaceEquipIndex(curPlayer, value): return curPlayer.SetExAttr15(value)
def SetLingGenMaxIndex(curPlayer):
    return
# 境界难度等级
def GetRealmDifficulty(curPlayer): return curPlayer.GetExAttr18()
def GetRealmDifficulty(curPlayer): return 0
def SetRealmDifficulty(curPlayer, realmDifficulty):
    ''' 设置境界难度等级,任何地图均可选择
    '''
    playerID = curPlayer.GetPlayerID()
    if realmDifficulty:
        needRealmLV = GetDifficultyRealmLV(realmDifficulty)
        curRealmLV = curPlayer.GetOfficialRank()
        if curRealmLV < needRealmLV:
            GameWorld.DebugLog("当前境界低于境界难度,无法选择! curRealmLV(%s) < %s" % (curRealmLV, needRealmLV), playerID)
            return
        difficultyRealmList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 2)
        if needRealmLV not in difficultyRealmList:
            GameWorld.ErrLog("realmDifficulty(%s) needRealmLV(%s) not in difficultyRealmList(%s)"
                             % (realmDifficulty, needRealmLV, difficultyRealmList), playerID)
            return
    GameWorld.DebugLog("SetRealmDifficulty: realmDifficulty=%s" % realmDifficulty, playerID)
    realmMapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    mapID = curPlayer.GetMapID()
    if mapID in realmMapIDList:
        # 先移除之前选的难度
        for playerIDList in PyGameData.g_realmDiffPlayerDict.values():
            if playerID in playerIDList:
                playerIDList.remove(playerID)
        # 加入新难度,0难度不处理
        if realmDifficulty:
            if realmDifficulty not in PyGameData.g_realmDiffPlayerDict:
                PyGameData.g_realmDiffPlayerDict[realmDifficulty] = []
            playerIDList = PyGameData.g_realmDiffPlayerDict[realmDifficulty]
            if playerID not in playerIDList:
                playerIDList.append(playerID)
        SetPlayerSightLevel(curPlayer, realmDifficulty)
    if curPlayer.GetExAttr18() != realmDifficulty:
        curPlayer.SetExAttr18(realmDifficulty)
        SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ExAttr18, realmDifficulty)
    return
def GetDifficultyRealmLV(realmDifficulty): return realmDifficulty % 1000
def GetDifficultyRealmLV(realmDifficulty): return 0
def GetMapRealmDifficulty(curPlayer):
    ## 获取玩家在本地图中的境界难度层级,必须在境界地图且有选择境界难度才算,否则为默认0;该难度值同时也是视野层级
    realmDifficulty = GetRealmDifficulty(curPlayer)
    if not realmDifficulty:
        return 0
    mapID = curPlayer.GetMapID()
    realmMapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    if mapID not in realmMapIDList:
        return 0
    return realmDifficulty
    return 0
##玩家离开仙盟时间(主动或被踢都算)
def GetLeaveFamilyTimeEx(curPlayer):return curPlayer.GetExAttr19()
@@ -6107,48 +4572,42 @@
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ExAttr19, value, 0, False)
    return
##获得玩家威望值
def GetPrestige(curPlayer): return 0
def SetPrestige(curPlayer, value): return
##总战斗力,支持超过20E = 各模块战力总和
def GetFightPower(curPlayer): return curPlayer.GetFightPowerEx() * ChConfig.Def_PerPointValue + curPlayer.GetFightPower()
def SetFightPower(curPlayer, value):
    beforeFightPower = GetFightPower(curPlayer)
    curPlayer.SetFightPower(value % ChConfig.Def_PerPointValue, value / ChConfig.Def_PerPointValue, False) # 不通知GameServer bNotifyGameServer False
    if value < beforeFightPower:
        DataRecordPack.DR_FightPowerChangeInfo(curPlayer, beforeFightPower)
    highestFightPower = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_Highest)
    highestFightPower += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_HighestEx) * ChConfig.Def_PerPointValue
    if value > highestFightPower:
        highestFightPower = value
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Highest, highestFightPower % ChConfig.Def_PerPointValue)
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_HighestEx, highestFightPower / ChConfig.Def_PerPointValue)
    GameWorld.DebugLog("总战力: %s, 历史最高战力: %s, beforeFightPower=%s" % (value, highestFightPower, beforeFightPower), curPlayer.GetPlayerID())
    PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
    # 记录开服活动数据
    #OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
    #if beforeFightPower != totalFightPower:
    #    CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
    return
## 设置模块战斗力,支持超过20E = 模块公式战力 + 技能附加战力 + 其他附加战力
def SetMFPFightPower(curPlayer, mfpType, fightPower):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPFightPower % mfpType, fightPower % ChConfig.Def_PerPointValue)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPFightPowerPoint % mfpType, fightPower / ChConfig.Def_PerPointValue)
    return
def SetMFPFightPower(curPlayer, mfpType, fightPower): return
## 获取模块战斗力
def GetMFPFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPFightPowerPoint % mfpType) * ChConfig.Def_PerPointValue + \
        curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPFightPower % mfpType)
def GetMFPFightPower(curPlayer, mfpType): return 0
## 设置模块附加战斗力,支持超过20E
def SetMFPExFightPower(curPlayer, mfpType, fightPower):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % mfpType, fightPower % ChConfig.Def_PerPointValue)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPExPoint % mfpType, fightPower / ChConfig.Def_PerPointValue)
    return
def SetMFPExFightPower(curPlayer, mfpType, fightPower): return
## 获取模块附加战斗力
def GetMFPExFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPExPoint % mfpType) * ChConfig.Def_PerPointValue + \
        curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPEx % mfpType)
def GetMFPExFightPower(curPlayer, mfpType): return 0
        
## 设置模块技能附加战斗力,支持超过20E
def SetMFPSkillFightPower(curPlayer, mfpType, fightPower):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkill % mfpType, fightPower % ChConfig.Def_PerPointValue)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkillEx % mfpType, fightPower / ChConfig.Def_PerPointValue)
    return
def SetMFPSkillFightPower(curPlayer, mfpType, fightPower): return
## 获取模块技能附加战斗力
def GetMFPSkillFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkillEx % mfpType) * ChConfig.Def_PerPointValue + \
        curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpType)
def GetMFPSkillFightPower(curPlayer, mfpType): return 0
        
#===============================================================================
##获取玩家分线信息
@@ -6187,19 +4646,6 @@
        atkInterval *= 100
    
    return atkInterval
def AddZhenQiByKillNPC(curPlayer, npcSP, killCount=1):
    ## 杀怪加真气
    if not npcSP:
        return
    addSPValue = npcSP * killCount
    npcSPRate = PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_NPCSPRate)
    if npcSPRate:
        npcHPRate = ChConfig.Def_MaxRateValue + npcSPRate
        addSPValue = int(addSPValue * npcHPRate / float(ChConfig.Def_MaxRateValue))
    PlayerAddZhenQi(curPlayer, addSPValue)
    return
##玩家增加真气
# @param curPlayer 玩家
@@ -6254,107 +4700,19 @@
    return True
## SP真气值 - 暂废弃 ExAttr7、ExAttr8 改为专精选择通知,用于前端表现其他玩家的不同专精特效
def GetZhenQi(curPlayer): return 0 #curPlayer.GetExAttr8() * ChConfig.Def_PerPointValue + curPlayer.GetExAttr7()
def SetZhenQi(curPlayer, totalZhenQi):
#    zhenQi = totalZhenQi % ChConfig.Def_PerPointValue
#    zhenQiPoint = min(totalZhenQi / ChConfig.Def_PerPointValue, ChConfig.Def_UpperLimit_DWord)
#    # 玩家单独通知,不广播; c++接口默认广播,故这里设置False
#    if zhenQi != curPlayer.GetExAttr7():
#        curPlayer.SetExAttr7(zhenQi)
#    if zhenQiPoint != curPlayer.GetExAttr8():
#        curPlayer.SetExAttr8(zhenQiPoint)
    return
def GetZhenQi(curPlayer): return 0
def SetZhenQi(curPlayer, totalZhenQi): return
#===============================================================================
# #@warning: ExAttr6~ExAttr10, 新增2个布尔默认参数, 是否通知客户端, 是否通知GameServer, 默认值为False
#===============================================================================
#---------------------------------------------------------------------------
##获取可免费开启的格子数
# @param curPlayer 玩家对象
# @param packType 背包类型
# @param openCnt 实际要开启的格子数
# @return 获取可免费开启的格子数
def GetCanAutoOpenPackCount(curPlayer, packType, openCnt, tick):
    if packType not in [IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse]:
        return 0
    cfgObj = PlayerExpandPackCfgMgr.GetExpandPackCfg(curPlayer, packType)
    #找不到这种背包的配置信息对象
    if not cfgObj:
        return 0
    #已购买或自动开启的格子数
    keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict[packType][ChConfig.Def_PlayerPackDict_Index_Key]
    curCount = curPlayer.NomalDictGetProperty(keyName)
#    nextCountIndex = curCount + 1
#    infoObj = cfgObj.GetAttrInfoByInex(nextCountIndex)
#    if None == infoObj:
#        return 0
#    #更新下玩家的在线时间
#    UpdateOnLineTime(curPlayer, tick)
#    onlineTime = curPlayer.GetOnlineTime()
#    #需要的时间
#    needOnlineTime = infoObj["OnlineTime"]
#    #最后一次自动开启背包的在线时间tick
#    lastAutoOpenPackTick = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_LastAutoOpenPackTick)
#    if onlineTime - lastAutoOpenPackTick > needOnlineTime:
#        return 1
#    return 0
    #最大可增加的背包数
    maxCanAddCount = cfgObj.GetCanAddCount()
    forCount = min(openCnt, maxCanAddCount - curCount)
    #可以再增加的格子数
    count = 0
    #遍历可增加的背包格子数
    UpdateOnLineTime(curPlayer, tick)
    onlineTime = curPlayer.GetOnlineTime()
    lastAutoOpenPackTick = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_LastAutoOpenPackTick % packType)
    lastInfoObj = cfgObj.GetTotalAddAttrInfoByCount(curCount)
    notOnlineTime = 0
    if lastInfoObj:
        notOnlineTime = lastInfoObj["OnlineTime"]
#    GameWorld.Log("get online time = %s"%onlineTime)
    for i in range(forCount):
        nextCount = curCount + i + 1
        infoObj = cfgObj.GetTotalAddAttrInfoByCount(nextCount)
        if None == infoObj:
            break
        # (小于0的不具有免费开启功能)
        if infoObj["OnlineTime"] < 0:
            continue
        needOnlineTime = infoObj["OnlineTime"] - notOnlineTime
#        GameWorld.Log("get need online time = %s"%needOnlineTime)
        #要求的在线时间,大于当前的在线时间,没办法加背包格子
        if needOnlineTime > onlineTime - lastAutoOpenPackTick:
            break
        count += 1
    return count
## 获取节假日经验加成
#  @param curPlayer: 玩家实例
#  @return: 节假日经验加成
def GetHolidayExpRate(curPlayer):
    return 0
## 获取世界boss经验加成
#  @param curPlayer: 玩家实例
#  @return: 世界boss经验加成
def GetWorldBossExpRate(curPlayer):
    return 0
## 获取玩家当前等级升级所需总经验
#  @param playerLv 玩家等级
#  @return 返回值, 升级需要的总经验
def GetLVUPTotalNeedExp(curPlayer):
    curLV = curPlayer.GetLV()
    #if curLV >= IpyGameDataPY.GetFuncCfg("PlayerMaxLV") and PlayerGreatMaster.IsGreatMasterOpen(curPlayer):
    #    return PlayerGreatMaster.GetTotalExpByGreatMasterLV(curPlayer.GetLV2())
    return GetTotalExpByPlayerLv(curLV)
## 根据等级获得升级需要的总经验
@@ -6376,7 +4734,7 @@
def GetLVUPTotalExpNeed(lvIpyData):
    if not lvIpyData:
        return 0
    return lvIpyData.GetExpPoint() * ChConfig.Def_PerPointValue + lvIpyData.GetExp()
    return lvIpyData.GetExp()
def GetPlayerMaxLV(curPlayer):
    ## 获取玩家实际可升的最大等级
@@ -6459,64 +4817,8 @@
#  @param allAttrList 属性列表
#  @return None
def CalcAttrDict_Type(attrType, value, allAttrList):
    if value == 0:
        return
    #[属性索引, 是否基础属性,(非)线性]
    attrInfo = ChConfig.ItemEffect_AttrDict.get(attrType, [])
    if attrInfo == []:
        return
    index = ChConfig.Def_CalcAttrIndexDict[(attrInfo[1], attrInfo[2])]
    attrDict = allAttrList[index]
    for i in attrInfo[0]:
        GameWorld.AddDictValue(attrDict, {i:value})
    return
def CalcAttrDict_TypeEx(attrType, value, allAttrDict):
    ## 统计玩家属性,累加
    if value == 0:
        return
    #[属性索引, 是否基础属性,(非)线性]
    attrInfo = ChConfig.ItemEffect_AttrDict.get(attrType, [])
    if attrInfo == []:
        return
    for i in attrInfo[0]:
        GameWorld.AddDictValue(allAttrDict, {i:value})
    return
#===============================================================================
# CalcAttr_Base,
# CalcAttr_BaseNoline,
# CalcAttr_Battle,
# CalcAttr_BattleNoline,
#===============================================================================
# 从srcAttrList计算出addAttrList带来的固定属性,用于后续计算使用
#===============================================================================
# def CalcAddFuncAttrByAttrList(srcAttrList, addAttrList):
#    for addKey, addValue in addAttrList[ChConfig.CalcAttr_BaseNoline].items():
#        value = srcAttrList[ChConfig.CalcAttr_Base].get(addKey, 0)
#        if value == 0:
#            continue
#
#        addAttrList[ChConfig.CalcAttr_Base][addKey]  = addAttrList[ChConfig.CalcAttr_Base].get(addKey, 0)\
#                                                         + value*addValue / ChConfig.Def_MaxRateValue
#
#    addAttrList[ChConfig.CalcAttr_BaseNoline] = {}
#    for addKey, addValue in addAttrList[ChConfig.CalcAttr_BattleNoline].items():
#        value = srcAttrList[ChConfig.CalcAttr_Battle].get(addKey, 0)
#        if value == 0:
#            continue
#
#        addAttrList[ChConfig.CalcAttr_Battle][addKey]  = addAttrList[ChConfig.CalcAttr_Battle].get(addKey, 0)\
#                                                         + value*addValue / ChConfig.Def_MaxRateValue
#
#    addAttrList[ChConfig.CalcAttr_BattleNoline] = {}
#    return addAttrList
#===============================================================================
## 培养境界等级
def GetTrainRealmLVReal(curPlayer, funcType):
    trainRealmLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TrainRealmLV % funcType)
@@ -6556,356 +4858,23 @@
def GetTotalLingGenPoint(curPlayer):
    # 总灵根点数(金木水火土+自由点数)
    attrIDList = [ShareDefine.Def_Effect_Metal, ShareDefine.Def_Effect_Wood, ShareDefine.Def_Effect_Water, ShareDefine.Def_Effect_Fire, ShareDefine.Def_Effect_Earth]
    curTotalPoint = 0
    for attrID in attrIDList:
        curTotalPoint += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % attrID)
    curTotalPoint += curPlayer.GetFreePoint()
    return curTotalPoint
    return 0
# 灵根 - 金木水火土
def GetMetal(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_Metal)
def SetMetal(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_Metal, value)
def GetWood(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_Wood)
def SetWood(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_Wood, value)
def GetWater(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_Water)
def SetWater(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_Water, value)
def GetFire(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_Fire)
def SetFire(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_Fire, value)
def GetEarth(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_Earth)
def SetEarth(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_Earth, value)
# 灵根品级 - 金木水火土
def GetMetalQualityLV(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MetalQualityLV)
def SetMetalQualityLV(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_MetalQualityLV, value)
def GetWoodQualityLV(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WoodQualityLV)
def SetWoodQualityLV(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WoodQualityLV, value)
def GetWaterQualityLV(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WaterQualityLV)
def SetWaterQualityLV(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WaterQualityLV, value)
def GetFireQualityLV(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FireQualityLV)
def SetFireQualityLV(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FireQualityLV, value)
def GetEarthQualityLV(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_EarthQualityLV)
def SetEarthQualityLV(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_EarthQualityLV, value)
def GetMetal(curPlayer): return 0
def GetWood(curPlayer): return 0
def GetWater(curPlayer): return 0
def GetFire(curPlayer): return 0
def GetEarth(curPlayer): return 0
#---玩家扩展接口, 战斗属性,不存数据库,只通知本人---
##玩家移动速度值, 不含buff对速度的影响; 功能等对速度的影响直接改变此值
def GetSpeedNotBuff(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SpeedValueNotBuff)
def SetSpeedNotBuff(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SpeedValueNotBuff, value)
##玩家移动速度值, 含buff对速度的影响; 此数值不是真正的移动速度,只是用于计算移动速度的参数值
def GetSpeedValue(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SpeedValue)
def SetSpeedValue(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SpeedValue, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_SpeedValue, value, True) # 移动速度值暂定广播周围玩家
##获取玩家攻击速度,用于计算攻击间隔
# @param curPlayer 玩家实例
# @return 玩家攻击速度
def GetAtkSpeed(curPlayer):
    return curPlayer.GetBattleValEx1()
##设置玩家攻击速度,用于计算攻击间隔
# @param curPlayer 玩家实例
# @return None
def SetAtkSpeed(curPlayer, value):
    curPlayer.SetBattleValEx1(value, True)
#---攻击回复血量比率----
## 获取玩家攻击回复血量比率
#  @param curPlayer 玩家实例
#  @return
def GetAtkBackHPPer(curPlayer):
    return curPlayer.GetBattleValEx2()
## 设置玩家攻击回复血量比率
#  @param curPlayer 玩家实例
#  @return None
def SetAtkBackHPPer(curPlayer, value):
    curPlayer.SetBattleValEx2(value)
## 获取玩家攻击回复蓝量比率
def GetAtkBackMPPer(curPlayer): return 0
def SetAtkBackMPPer(curPlayer, value): return
## 玩家减技能CD比例
def GetReduceSkillCDPer(curPlayer): return curPlayer.GetBattleValEx3()
def SetReduceSkillCDPer(curPlayer, reducePer): return curPlayer.SetBattleValEx3(reducePer)
def GetReduceSkillCDPer(curPlayer): return 0
def SetReduceSkillCDPer(curPlayer, reducePer): return
## 常规地图经验倍率加成
def GetCommMapExpRate(curPlayer):
    if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull:
        return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CommMapExpRate)
    return 0
def SetCommMapExpRate(curPlayer, expRate): return curPlayer.SetDict(ChConfig.Def_PlayerKey_CommMapExpRate, expRate)
## 对怪物伤害加成
def GetNPCHurtAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_NPCHurtAddPer)
def SetNPCHurtAddPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_NPCHurtAddPer, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_NPCHurtAddPer, value)
#---职业伤害加成---
## 目标战士伤害加成
def GetJobAHurtAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobAHurtAddPer)
def SetJobAHurtAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobAHurtAddPer, value)
## 目标法师伤害加成
def GetJobBHurtAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobBHurtAddPer)
def SetJobBHurtAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobBHurtAddPer, value)
## 目标弓手伤害加成
def GetJobCHurtAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobCHurtAddPer)
def SetJobCHurtAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobCHurtAddPer, value)
#---伤害减免---
## NPC攻击伤害减免
def GetNPCAtkReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_NPCAtkReducePer)
def SetNPCAtkReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_NPCAtkReducePer, value)
## 战士攻击伤害减免
def GetJobAAtkReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobAAtkReducePer)
def SetJobAAtkReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobAAtkReducePer, value)
## 法师攻击伤害减免
def GetJobBAtkReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobBAtkReducePer)
def SetJobBAtkReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobBAtkReducePer, value)
## 弓手攻击伤害减免
def GetJobCAtkReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_JobCAtkReducePer)
def SetJobCAtkReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_JobCAtkReducePer, value)
#---特殊伤害减免---
## 会心一击伤害减免固定值
def GetLuckyHitReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_LuckyHitReduce)
def SetLuckyHitReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_LuckyHitReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_LuckyHitReduce, value)
## 卓越一击伤害减免
def GetGreatHitReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GreatHitReducePer)
def SetGreatHitReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GreatHitReducePer, value)
## 暴击伤害减免
def GetSuperHitReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuperHitReduce)
def SetSuperHitReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SuperHitReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_SuperHitReduce, value)
## 无视防御伤害减免
def GetIgnoreDefReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_IgnoreDefReducePer)
def SetIgnoreDefReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_IgnoreDefReducePer, value)
#---抗特殊伤害概率---
## 抗会心一击概率
def GetLuckyHitRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_LuckyHitRateReduce)
def SetLuckyHitRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_LuckyHitRateReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_LuckyHitRateReduce, value)
## 抗卓越一击概率
def GetGreatHitRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GreatHitRateReduce)
def SetGreatHitRateReduce(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GreatHitRateReduce, value)
## 抗暴击概率
def GetSuperHitRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuperHitRateReduce)
def SetSuperHitRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SuperHitRateReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_SuperHitRateReduce, value)
## 抗无视防御概率
def GetIgnoreDefRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_IgnoreDefRateReduce)
def SetIgnoreDefRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_IgnoreDefRateReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_IgnoreDefRateReduce, value)
#---特殊伤害概率---
## 富豪一击概率
def GetFuhaoHitRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FuhaoHitRate)
def SetFuhaoHitRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FuhaoHitRate, value)
## 流血伤害
def GetBleedDamage(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BleedDamage)
def SetBleedDamage(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_BleedDamage, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_BleedDamage, value)
## Boss最终伤害百分比
def GetBossFinalHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BossFinalHurtPer)
def SetBossFinalHurtPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_BossFinalHurtPer, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_BossFinalHurtPer, value)
## 最终伤害百分比
def GetFinalHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurtPer)
def SetFinalHurtPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurtPer, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FinalHurtPer, value)
## 最终伤害减免百分比
def GetFinalHurtReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurtReducePer)
def SetFinalHurtReducePer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurtReducePer, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FinalHurtReducePer, value)
## 最终固定伤害增加
def GetFinalHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurt)
def SetFinalHurt(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurt, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FinalHurt, value)
## 最终固定伤害减少
def GetFinalHurtReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurtReduce)
def SetFinalHurtReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurtReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FinalHurtReduce, value)
## 对指定boss伤害加成固定值
def GetBossIDHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BossIDHurt)
def SetBossIDHurt(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BossIDHurt, value)
## 对指定boss伤害加成倍率
def GetBossIDHurtAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BossIDHurtAddPer)
def SetBossIDHurtAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BossIDHurtAddPer, value)
## 装备掉落执行次数加成万分率
def GetDropEquipDoCount(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_DropEquipDoCount)
def SetDropEquipDoCount(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_DropEquipDoCount, value)
# 基础攻击百分比
def GetBaseAtkAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseAtkAddPer)
def SetBaseAtkAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseAtkAddPer, value)
# 基础生命百分比
def GetBaseMaxHPAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseMaxHPAddPer)
def SetBaseMaxHPAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseMaxHPAddPer, value)
# 基础防御百分比
def GetBaseDefAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseDefAddPer)
def SetBaseDefAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseDefAddPer, value)
# 基础命中百分比
def GetBaseHitAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseHitAddPer)
def SetBaseHitAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseHitAddPer, value)
# 基础闪避百分比
def GetBaseMissAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BaseMissAddPer)
def SetBaseMissAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BaseMissAddPer, value)
# 法器生命百分比
def GetFaQiMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiMaxHPPer)
def SetFaQiMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiMaxHPPer, value)
# 法器攻击百分比
def GetFaQiAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiAtkPer)
def SetFaQiAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiAtkPer, value)
# 法器防御百分比
def GetFaQiDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaQiDefPer)
def SetFaQiDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaQiDefPer, value)
# 神兵生命百分比
def GetGodWeaponMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GodWeaponMaxHPPer)
def SetGodWeaponMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GodWeaponMaxHPPer, value)
# 神兵攻击百分比
def GetGodWeaponAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GodWeaponAtkPer)
def SetGodWeaponAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GodWeaponAtkPer, value)
# 宝石生命百分比
def GetStoneMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_StoneMaxHPPer)
def SetStoneMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_StoneMaxHPPer, value)
# 宝石攻击百分比
def GetStoneAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_StoneAtkPer)
def SetStoneAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_StoneAtkPer, value)
# 血瓶恢复效果
def GetHPCureEnhance(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HPCureEnhance)
def SetHPCureEnhance(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HPCureEnhance, value)
# 额外输出伤害
def GetOnlyFinalHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_OnlyFinalHurt)
def SetOnlyFinalHurt(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_OnlyFinalHurt, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_OnlyFinalHurt, value)
    return
# PVP攻击回血
def GetPVPAtkBackHP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PVPAtkBackHP)
def SetPVPAtkBackHP(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PVPAtkBackHP, value)
# 命中成功率
def GetHitSucessRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HitSucessRate)
def SetHitSucessRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HitSucessRate, value)
# 闪避成功率
def GetMissSucessRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MissSucessRate)
def SetMissSucessRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_MissSucessRate, value)
# 治疗加成 默认百分百
def GetCurePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CurePer)
def SetCurePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_CurePer, value)
# 加深受到伤害百分比
def GetBeHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BeHurtPer)
def SetBeHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BeHurtPer, value)
# 称号生命加成
def GetTitleMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TitleMaxHPPer)
def SetTitleMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_TitleMaxHPPer, value)
# 称号攻击加成
def GetTitleAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TitleAtkPer)
def SetTitleAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_TitleAtkPer, value)
# 称号防御加成
def GetTitleDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TitleDefPer)
def SetTitleDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_TitleDefPer, value)
# 头像生命加成
def GetFaceMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaceMaxHPPer)
def SetFaceMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaceMaxHPPer, value)
# 头像攻击加成
def GetFaceAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaceAtkPer)
def SetFaceAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaceAtkPer, value)
# 头像防御加成
def GetFaceDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FaceDefPer)
def SetFaceDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FaceDefPer, value)
# 头像框生命加成
def GetFacePicMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FacePicMaxHPPer)
def SetFacePicMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FacePicMaxHPPer, value)
# 头像框攻击加成
def GetFacePicAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FacePicAtkPer)
def SetFacePicAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FacePicAtkPer, value)
# 头像框防御加成
def GetFacePicDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FacePicDefPer)
def SetFacePicDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FacePicDefPer, value)
# 坐骑幻化生命加成
def GetHorseSkinMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseSkinMaxHPPer)
def SetHorseSkinMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseSkinMaxHPPer, value)
# 坐骑幻化攻击加成
def GetHorseSkinAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseSkinAtkPer)
def SetHorseSkinAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseSkinAtkPer, value)
# 坐骑幻化防御加成
def GetHorseSkinDefPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseSkinDefPer)
def SetHorseSkinDefPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseSkinDefPer, value)
# 坐骑攻击百分比
def GetHorseAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseAtkPer)
def SetHorseAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseAtkPer, value)
# 坐骑生命加成
def GetHorseMaxHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseMaxHPPer)
def SetHorseMaxHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseMaxHPPer, value)
# 灵宠攻击加成
def GetPetAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PetAtkPer)
def SetPetAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PetAtkPer, value)
# 坐骑培养属性加成
def GetHorseTrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseTrainAttrPer)
def SetHorseTrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseTrainAttrPer, value)
# 灵宠培养属性加成
def GetPetTrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PetTrainAttrPer)
def SetPetTrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PetTrainAttrPer, value)
# 守护培养属性加成
def GetGuardTrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GuardTrainAttrPer)
def SetGuardTrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GuardTrainAttrPer, value)
# 翅膀培养属性加成
def GetWingTrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WingTrainAttrPer)
def SetWingTrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WingTrainAttrPer, value)
# 灭世培养属性加成
def GetPeerlessWeaponTrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PeerlessWeaponTrainAttrPer)
def SetPeerlessWeaponTrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PeerlessWeaponTrainAttrPer, value)
# 弑神培养属性加成
def GetPeerlessWeapon2TrainAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PeerlessWeapon2TrainAttrPer)
def SetPeerlessWeapon2TrainAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PeerlessWeapon2TrainAttrPer, value)
# 炼体属性属性加成
def GetLianTiAttrPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_LianTiAttrPer)
def SetLianTiAttrPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_LianTiAttrPer, value)
def GetAttr160(curPlayer): return 0
def SetAttr160(curPlayer, value): pass
def GetHPCureEnhance(curPlayer): return 0
# 仙盟徽章ID
def GetFamilyEmblemID(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyEmblemID)
@@ -6919,355 +4888,39 @@
    curPlayer.SetFamilyMemberLV(fmLV) # 也同步设置该值,防止有些地方直接调用 curPlayer.GetFamilyMemberLV()
    return
# 仙盟事务速度加成
def GetAffairSpeedPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AffairSpeedPer)
def SetAffairSpeedPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AffairSpeedPer, value)
# 仙盟BOSS伤害加成
def GetFamilyBossHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FamilyBossHurtPer)
def SetFamilyBossHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilyBossHurtPer, value)
# 仙盟联赛生命加成
def GetFamilyWarHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FamilyWarHPPer)
def SetFamilyWarHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilyWarHPPer, value)
# 仙盟联赛攻击加成
def GetFamilyWarAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FamilyWarAtkPer)
def SetFamilyWarAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilyWarAtkPer, value)
# 仙盟打坐经验加成
def GetFamilySitExpPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FamilySitExpPer)
def SetFamilySitExpPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilySitExpPer, value)
# 宝石基础属性百分比
def GetStoneBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_StoneBasePer)
def SetStoneBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_StoneBasePer, value)
# 境界基础属性百分比
def GetRealmBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RealmBasePer)
def SetRealmBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_RealmBasePer, value)
# 翅膀生命百分比
def GetWingHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WingHPPer)
def SetWingHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WingHPPer, value)
# 套装基础属性百分比
def GetSuiteBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuiteBasePer)
def SetSuiteBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SuiteBasePer, value)
# 强化基础攻击百分比
def GetPlusBaseAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PlusBaseAtkPer)
def SetPlusBaseAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PlusBaseAtkPer, value)
## 暂无用
#  @param curPlayer 玩家实例
#  @return
def GetAddBackHPPer(curPlayer):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AddBackHPPer)
## 暂无用
#  @param curPlayer 玩家实例
#  @return None
def SetAddBackHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AddBackHPPer, value)
#---降低生命恢复效果----
## 获取降低生命恢复效果万分率
#  @param curPlayer 玩家实例
#  @return
def GetReduceBackHPPer(curPlayer):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ReduceBackHPPer)
## 设置降低生命恢复效果万分率
#  @param curPlayer 玩家实例
#  @return None
def SetReduceBackHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ReduceBackHPPer, value)
#---触发击晕----
def GetFaintRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrFaintRate)
def SetFaintRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrFaintRate, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FaintRate, value)
#---击晕抵抗----
def GetFaintDefRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrFaintDefRate)
def SetFaintDefRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrFaintDefRate, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_FaintDefRate, value)
#---触发定身----
def GetAtkerFreezed(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrAtkerFreezed)
def SetAtkerFreezed(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrAtkerFreezed, value)
#---增加仇恨----
def GetAddAngry(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrAddAngry)
def SetAddAngry(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrAddAngry, value)
#---连击几率----
def GetComboRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrComboRate)
def SetComboRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrComboRate, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ComboRate, value)
#---连击伤害----
def GetComboDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrComboDamPer)
def SetComboDamPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrComboDamPer, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ComboDamPer, value)
#---技能攻击比例减少----
def GetSkillAtkRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAtkRateReduce)
def SetSkillAtkRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAtkRateReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_SkillAtkRateReduce, value)
#---PVP固定伤害----
def GetDamagePVP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePVP)
def SetDamagePVP(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePVP, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamagePVP, value)
#---PVP固定伤害减少----
def GetDamagePVPReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePVPReduce)
def SetDamagePVPReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePVPReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamagePVPReduce, value)
#---伤害输出固定值计算对NPC附加----
def GetDamagePVE(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePVE)
def SetDamagePVE(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePVE, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamagePVE, value)
#---伤害输出计算百分比对玩家附加----
def GetDamagePerPVP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePerPVP)
def SetDamagePerPVP(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePerPVP, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamagePerPVP, value)
def GetDamagePerPVPReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePerPVPReduce)
def SetDamagePerPVPReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePerPVPReduce, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamagePerPVPReduce, value)
#---受伤计算百分比----
def GetHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrHurtPer)
def SetHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrHurtPer, value)
#---自动恢复XP值比率----
def GetXPRestorePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrXPRestorePer)
def SetXPRestorePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrXPRestorePer, value)
#---魔法盾伤害吸收蓝耗比率----
def GetShieldMPCostRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrShieldMPCostRate)
def SetShieldMPCostRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrShieldMPCostRate, value)
#---20%的概率抵御伤害比率----
def GetDamChanceDef(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamChanceDef)
def SetDamChanceDef(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamChanceDef, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_DamChanceDef, value)
#---当前防护值,需存DB----
def GetProDef(curPlayer): return curPlayer.GetExAttr4()
def SetProDef(curPlayer, value):
    curPlayer.SetExAttr4(value, True)
    return
def GetProDef(curPlayer): return 0
def SetProDef(curPlayer, value): return
#---最大防护值----
def GetMaxProDef(curPlayer): return curPlayer.GetExAttr16()
def SetMaxProDef(curPlayer, value):
    value = min(value, ChConfig.Def_UpperLimit_DWord)
    curPlayer.SetExAttr16(value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_MaxProDef, value, 0, True) # 周围玩家需要通知
    return
#---生命上限换算为防护值的百分比----
def GetProDefHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefHPPer)
def SetProDefHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefHPPer, value)
    #SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ProDefHPPer, value)
#---防护值吸收伤害比率----
def GetProDefAbsorb(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefAbsorb)
def SetProDefAbsorb(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefAbsorb, value)
    #SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ProDefAbsorb, value)
#---宠物攻击提升值----
def GetPetMinAtk(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetMinAtk)
def SetPetMinAtk(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetMinAtk, value)
def GetPetMaxAtk(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetMaxAtk)
def SetPetMaxAtk(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetMaxAtk, value)
#---宠物伤害百分比提升----移到GameObj下
#===============================================================================
# def GetPetDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetDamPer)
# def SetPetDamPer(curPlayer, value):
#    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetDamPer, value)
#    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_PetDamPer, value)
#===============================================================================
#---宠物技能伤害百分比提升----
def GetPetSkillAtkRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PetSkillAtkRate)
def SetPetSkillAtkRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PetSkillAtkRate, value)
#---每1级+%s攻击, 数值取万分率,支持小数算法----
def GetPerLVAtk(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPerLVAtk)
def SetPerLVAtk(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPerLVAtk, value)
#---每1级+%s生命, 数值为固定值----
def GetPerLVMaxHP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPerLVMaxHP)
def SetPerLVMaxHP(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPerLVMaxHP, value)
#---装备掉率----
def GetDropEquipPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDropEquipPer)
def SetDropEquipPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDropEquipPer, value)
#---功能层防御值----
def GetFuncDef(curPlayer): return EffGetSet.GetCopyFuncAttrValue(curPlayer, ChConfig.TYPE_Calc_AttrDEF)
def SetFuncDef(curPlayer, value): EffGetSet.SetCopyFuncAttrValue(curPlayer, ChConfig.TYPE_Calc_AttrDEF, value)
#普通攻击增伤:普通攻击附加的固定值伤害
def GetNormalHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_NormalHurt)
def SetNormalHurt(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_NormalHurt, value)
#普通攻击加成:普通攻击附加的伤害百分比
def GetNormalHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_NormalHurtPer)
def SetNormalHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_NormalHurtPer, value)
#法宝技能增伤:法宝技能攻击附加的固定值伤害
def GetFabaoHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FabaoHurt)
def SetFabaoHurt(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FabaoHurt, value)
#法宝技能加成:法宝技能攻击附加的伤害百分比
def GetFabaoHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FabaoHurtPer)
def SetFabaoHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FabaoHurtPer, value)
def GetMaxProDef(curPlayer): return 0
def SetMaxProDef(curPlayer, value): return
# 每X秒自动消失一个印记, 毫秒记录
def GetLostYinjiTime(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_LostYinjiTime)
def SetLostYinjiTime(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_LostYinjiTime, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_YinjiTime, value)
def GetLostYinjiTime(curPlayer): return 0
def SetLostYinjiTime(curPlayer, value): return
# 当前印记数
def GetYinjiCnt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_YinjiCnt)
def SetYinjiCnt(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_YinjiCnt, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_YinjiCnt, value)
def GetYinjiCnt(curPlayer): return 0
def SetYinjiCnt(curPlayer, value): return
# 减少指定技能组CD XX%
def GetTheFBSkillsCD(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TheFBSkillsCD)
def SetTheFBSkillsCD(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_TheFBSkillsCD, value)
def GetTheFBSkillsCD(curPlayer): return 0
def SetTheFBSkillsCD(curPlayer, value): return
# 灼烧固定伤害
def GetBurnValue(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BurnValue)
def SetBurnValue(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BurnValue, value)
def GetBurnValue(curPlayer): return 0
def SetBurnValue(curPlayer, value): return
# 延长灼烧时间百分比
def GetBurnTimePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BurnTimePer)
def SetBurnTimePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BurnTimePer, value)
def GetBurnTimePer(curPlayer): return 0
def SetBurnTimePer(curPlayer, value): return
# 减移动速度百分比
def GetSubSpeedPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SubSpeedPer)
def SetSubSpeedPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SubSpeedPer, value)
# 技能伤害增强
def GetSkillAddPer1(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer1)
def SetSkillAddPer1(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer1, value)
def GetSkillAddPer2(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer2)
def SetSkillAddPer2(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer2, value)
def GetSkillAddPer3(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer3)
def SetSkillAddPer3(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer3, value)
def GetSkillAddPer4(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer4)
def SetSkillAddPer4(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer4, value)
def GetSkillAddPer5(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer5)
def SetSkillAddPer5(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer5, value)
def GetSkillAddPer6(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer6)
def SetSkillAddPer6(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer6, value)
def GetSkillAddPer7(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAddPer7)
def SetSkillAddPer7(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAddPer7, value)
# 受到技能伤害减少
def GetSkillReducePer1(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer1)
def SetSkillReducePer1(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer1, value)
def GetSkillReducePer2(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer2)
def SetSkillReducePer2(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer2, value)
def GetSkillReducePer3(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer3)
def SetSkillReducePer3(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer3, value)
def GetSkillReducePer4(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer4)
def SetSkillReducePer4(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer4, value)
def GetSkillReducePer5(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer5)
def SetSkillReducePer5(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer5, value)
def GetSkillReducePer6(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer6)
def SetSkillReducePer6(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer6, value)
def GetSkillReducePer7(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillReducePer7)
def SetSkillReducePer7(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillReducePer7, value)
#---诛仙一击概率---
def GetZhuXianRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ZhuxianRate)
def SetZhuXianRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_ZhuxianRate, value)
#---诛仙护体减伤---
def GetZhuXianReducePer(curPlayer): return 0#curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ZhuXianReducePer)
def SetZhuXianReducePer(curPlayer, value): return #curPlayer.SetDict(ChConfig.Def_PlayerKey_ZhuXianReducePer, value)
## 计算功能背包物品属性
#  @param curPlayer 当前玩家
#  @param packType 背包类型
#  @param allAttrListEquip 属性列表
#  @return None
def CalcFuncPackItem(curPlayer, packType, allAttrListEquip):
    #===========================================================================
    # funcPack = curPlayer.GetItemManager().GetPack(packType)
    # equipPartIndexList = ChConfig.Pack_EquipPart_CanPlusStar.get(packType, [])
    #
    # #玩家当前可装备的装备类型
    # for equipIndex in range(0, funcPack.GetCount()):
    #
    #    curEquip = funcPack.GetAt(equipIndex)
    #    if curEquip.IsEmpty():
    #        continue
    #
    #    #计算效果
    #    for i in range(0, curEquip.GetEffectCount()):
    #        curEffect = curEquip.GetEffectByIndex(i)
    #        if not curEffect:
    #            break
    #
    #        effectID = curEffect.GetEffectID()
    #        if effectID == 0:
    #            #最后一个
    #            break
    #
    #        effectValue = curEffect.GetEffectValue(0)
    #        if not effectValue:
    #            continue
    #
    #        #添加物品效果的属性值
    #        CalcAttrDict_Type(effectID, effectValue, allAttrListEquip)
    #
    #
    #===========================================================================
    return
def GetSubSpeedPer(curPlayer): return 0
def SetSubSpeedPer(curPlayer, value): return
#-------------------------------------------------------------------------------
## 设置保存功能事先计算好的属性值
def SetCalcAttrListValue(curPlayer, funcIndex, allAttrList, insidePerAttrDict=None, customAttrDict=None):
    # 设置值之前先清空重置
    # @param customAttrDict: 自定义的属性信息,必须是格式 {"自定义属性描述名key":属性信息, ...}  自定义属性描述名key - 建议不同功能点之间不要重复
    ClearCalcAttrListValue(curPlayer, funcIndex)
    if insidePerAttrDict == None:
        insidePerAttrDict = {}
    if customAttrDict == None:
        customAttrDict = {}
    battleAttrDict = allAttrList[ChConfig.CalcAttr_Battle]
    if ChConfig.TYPE_Calc_PerLVAtk in battleAttrDict:
        # 每1级加的攻击力不一定满1点,所以这里按万分率来算,支持小数算法
        addAtk = int(curPlayer.GetLV() * battleAttrDict[ChConfig.TYPE_Calc_PerLVAtk] / float(ShareDefine.Def_MaxRateValue))
        battleAttrDict[ChConfig.TYPE_Calc_AttrATKMin] = battleAttrDict.get(ChConfig.TYPE_Calc_AttrATKMin, 0) + addAtk
        battleAttrDict[ChConfig.TYPE_Calc_AttrATKMax] = battleAttrDict.get(ChConfig.TYPE_Calc_AttrATKMax, 0) + addAtk
    if ChConfig.TYPE_Calc_PerLVMaxHP in battleAttrDict:
        # 每1级加的生命值不会少于1点,所以直接乘
        addMaxHP = curPlayer.GetLV() * battleAttrDict[ChConfig.TYPE_Calc_PerLVMaxHP]
        battleAttrDict[ChConfig.TYPE_Calc_AttrMaxHP] = battleAttrDict.get(ChConfig.TYPE_Calc_AttrMaxHP, 0) + addMaxHP
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_playerFuncAttrDict:
        PyGameData.g_playerFuncAttrDict[playerID] = {}
    funcAttrDict = PyGameData.g_playerFuncAttrDict[playerID]
    funcAttrDict[funcIndex] = [allAttrList, insidePerAttrDict, customAttrDict]
    #GameWorld.DebugLog("保存功能点属性: funcIndex=%s, %s, %s" % (funcIndex, allAttrList, insidePerAttrDict))
    return
def GetCalcAttrListValue(curPlayer, funcIndex):
@@ -7275,57 +4928,7 @@
    attrList = [{} for _ in range(4)]
    insidePerAttrDict = {}
    customAttrDict = {}
    if isinstance(funcIndex, int):
        funcIndexList = [funcIndex]
    elif isinstance(funcIndex, list):
        funcIndexList = funcIndex
    else:
        return attrList, insidePerAttrDict, customAttrDict
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_playerFuncAttrDict:
        return attrList, insidePerAttrDict, customAttrDict
    funcAttrDict = PyGameData.g_playerFuncAttrDict[playerID]
    for funcIndex in funcIndexList:
        if funcIndex not in funcAttrDict:
            continue
        funcAttrList, funcInsidePerAttrDict, funcCustomAttrDict = funcAttrDict[funcIndex]
        for i, attrDict in enumerate(attrList):
            curAttrDict = funcAttrList[i]
            AddAttrDictValue(attrDict, curAttrDict)
        customAttrDict.update(funcCustomAttrDict)
        AddAttrDictValue(insidePerAttrDict, funcInsidePerAttrDict)
    return attrList, insidePerAttrDict, customAttrDict
## 重置缓存
def ClearCalcAttrListValue(curPlayer, funcIndex):
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_playerFuncAttrDict:
        return
    funcAttrDict = PyGameData.g_playerFuncAttrDict[playerID]
    funcAttrDict.pop(funcIndex, None)
    return
def AddAttrListValue(attrList):
    addAttrList = [{} for _ in range(4)]
    for aList in attrList:
        for i in ChConfig.CalcAttrIndexList:
            AddAttrDictValue(addAttrList[i], aList[i])
    return addAttrList
## 属性值字典累加
def AddAttrDictValue(dict1, dict2):
    for key, value in dict2.items():
        if key not in dict1:
            dict1[key] = value
        else:
            aValue = dict1[key]
            if key in ChConfig.TYPE_Calc_DeclineList:
                # 这种算法的属性一般是万分率的,最大不超过百分百,故暂默认万分率, 若有不是万分率的属性再做处理
                dict1[key] = 10000 - (10000 - aValue) * (10000 - value)
            else:
                dict1[key] = aValue + value
    return
#-------------------------------------------------------------------------------
## 设置玩家字典值, 存库