ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -64,7 +64,7 @@
import PlayerGameEvent
import EventReport
import PlayerTeHui
import GameLogic_XMZZ
import PlayerGatherSoul
import PlayerSuccess
import PlayerPet
import PlayerGreatMaster
@@ -83,6 +83,8 @@
import PlayerFamilyTech
import PlayerCostRebate
import PlayerFairyCeremony
import FunctionNPCCommon
import CrossRealmPlayer
import ChNetSendPack
import PlayerState
import QuestCommon
@@ -161,7 +163,7 @@
# notifyCnt 代表广播周围玩家的数量,0为全部广播 -1为指定列表随机, 其他数字为指定指
def PyNotifyAll(curPlayer, sendPack, notifySelf=True, notifyCnt=0):
    if notifyCnt == -1:
        notifyCnt = random.choice((10, 10, 15, 15, 20, 25, 30, 50))
        notifyCnt = 8
    #GameWorld.DebugLog("PyNotifyAll %s"%notifyCnt)
    curPlayer.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength(), notifySelf, notifyCnt)
@@ -1316,15 +1318,17 @@
def GetPlayerLeaveServerTick(playerID):
    # 获取玩家从本地图中离线时的tick, 最大支持1小时, 如果有需要大于1小时的请调整超时限制
    # 注: 返回值为None时,只能代表玩家不是在本地图离线1小时内,并不能代表玩家当前是否在线状态,可能在其他地图
    # 注: 返回值为0时,只能代表玩家不是在本地图离线1小时内,并不能代表玩家当前是否在线状态,可能在其他地图
    if playerID not in PyGameData.g_disconnectPlayer:
        return
        return 0
    return PyGameData.g_disconnectPlayer[playerID][0]
def GetPlayerLeaveServerPos(playerID):
    # 获取玩家从本地图中离线时的坐标
    # 注:使用本函数时,一定要先使用函数 GetPlayerLeaveServerTick 确保是从本地图中离线的才可使用
    # @return: posX, posY
    if playerID not in PyGameData.g_disconnectPlayer:
        return
        return 0, 0
    return PyGameData.g_disconnectPlayer[playerID][1:3]
def RemoveTimeoutLeaveServerPlayerInfo(tick):
@@ -1423,7 +1427,8 @@
    
    FBLogic.DoPlayerChangeMapLogic(curPlayer, tick)
    #summonList = list()
    #召回宠物
    PetControl.ReCallFightPet(curPlayer)
    #1. 删除自己不需要的召唤兽(火焰之灵等)
    #必须用while, 因为在循环中要删除
    # 召唤兽切地图不带过去
@@ -1451,6 +1456,24 @@
#        summonIndex += 1
        
    
    # 更新最后一次离开的非中立常规地图, 从中立地图退出时需要回到该地方,必须在 DoResetWorldPosAndClear 之前更新
    if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull and curPlayer.GetMapID() not in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4):
        mapID = curPlayer.GetMapID()
        posX = curPlayer.GetPosX()
        posY = curPlayer.GetPosY()
        lineID = curPlayer.GetClientLineID()
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromMapID, mapID)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromPosX, posX)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromPosY, posY)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromLineID, lineID)
        GameWorld.DebugLog("最后一次离开的非中立常规地图更新!mapID=%s,lineID=%s,Pos(%s,%s)" % (mapID, lineID, posX, posY))
    else:
        mapID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromMapID)
        posX = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromPosX)
        posY = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromPosY)
        lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromLineID)
        GameWorld.DebugLog("最后一次离开的非中立常规地图不变!mapID=%s,lineID=%s,Pos(%s,%s)" % (mapID, lineID, posX, posY))
    #2. 调用切换地图接口
    curPlayer.DoResetWorldPosAndClear()
    
@@ -1478,11 +1501,37 @@
        GameServerRefresh.Set_PlayerRouteServerInitOK_OnLeaveFB(curPlayer, 1)
        return
    
    GameWorld.Log("PlayerLeaveFB...", curPlayer.GetPlayerID())
    if GameWorld.IsCrossServer():
        CrossRealmPlayer.PlayerExitCrossServer(curPlayer)
        return
    #中立地图回到上一次非中立常规地图
    if curPlayer.GetMapID() in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4):
        mapID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromMapID)
        posX = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromPosX)
        posY = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromPosY)
        lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromLineID)
        # 老号支持,本来就在中立地图的,返回新手村
        if not mapID:
            # {ְҵ:[dataMapID,posX,posY], ...}
            createRoleMapDict = IpyGameDataPY.GetFuncEvalCfg("CreateRoleMap", 1, {})
            if not createRoleMapDict:
                return
            job = curPlayer.GetJob()
            lineID = 0
            if job in createRoleMapDict:
                mapID, posX, posY = createRoleMapDict[job]
            else:
                mapInfoList = createRoleMapDict.values()
                mapID, posX, posY = mapInfoList[0]
    #离开副本
    mapID = curPlayer.GetFromMapID()
    posX = curPlayer.GetFromPosX()
    posY = curPlayer.GetFromPosY()
    else:
        mapID = curPlayer.GetFromMapID()
        posX = curPlayer.GetFromPosX()
        posY = curPlayer.GetFromPosY()
        lineID = curPlayer.GetFromLineID()
    if mapID == curPlayer.GetMapID():
        # 如果在同一张地图, 取DB重生点, 普通地图下线重上时FromMapID会被设置为本地图
        gameMap = GameWorld.GetMap()
@@ -1492,7 +1541,7 @@
    #copyMapID = curPlayer.GetCopyMapID()
    GameWorld.Log("PlayerLeaveFB MapID = %d, PosX = %d, PosY = %d" % (mapID, posX, posY), curPlayer.GetPlayerID())
    
    if GameWorld.GetMap().GetAutoSize() and GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount() == 1:
    if GameWorldProcess.IsNoPlayerNeedCloseFB() and GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount() == 1:
        #如果副本中只有这一个人, 那么把这个副本设置为玩家安全下线, 关闭副本
        gameFB = GameWorld.GetGameFB()
        gameFB.SetIsSafeClose(1)
@@ -1505,7 +1554,7 @@
    #    ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
    #===============================================================================================
    
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, curPlayer.GetFromLineID())
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, lineID)
    
    #在空闲或者移动状态下,才能锁死玩家
    if curPlayer.GetPlayerAction() in [IPY_GameWorld.paNull] or curPlayer.IsMoving():
@@ -3318,18 +3367,33 @@
# @remarks 获得玩家升级, 获得的属性点
def GetLvUp_AddPoint(curPlayer):
    curPlayerID = curPlayer.GetID()
    curReinCnt = curPlayer.GetReincarnationLv() # 当前转生次数
    curLV = curPlayer.GetLV() # 当前等级
    
    addPointList = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1)
    addPoint = addPointList[-1] if curReinCnt >= len(addPointList) else addPointList[curReinCnt]
    addPointDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1, {})
    addPoint = GameWorld.GetDictValueByRangeKey(addPointDict, curLV, 0)
    
    if addPoint == None:
        raise Exception('玩家获得升级属性点异常, reincarnationLv = %s PlayerID = %s' % (curReinCnt, curPlayerID))
        raise Exception('玩家获得升级属性点异常, curLV = %s PlayerID = %s' % (curLV, curPlayerID))
        return
    
    return int(addPoint)
def DoAddPointOpen(curPlayer):
    '''加点功能开启 处理给自由属性点及老号处理
                    清除老服玩家未加点的点数(清零),以前加的加点属性不清除,属性不变,战力不减, 根据最新的加点开启等级和老服玩家的当前等级,相差的差值给予玩家对应的加点点数'''
    beforeFreePoint = curPlayer.GetFreePoint()
    addPointDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1, {})
    initFreePoint = IpyGameDataPY.GetFuncCfg("LVUPAddPoint", 2)
    openLV = GameFuncComm.GetFuncLimitLV(ShareDefine.GameFuncID_AddPoint)
    setFreePoint = initFreePoint
    curLV = curPlayer.GetLV()
    for lv in xrange(openLV, curLV+1):
        setFreePoint += GameWorld.GetDictValueByRangeKey(addPointDict, lv, 0)
    addDataDict = {'beforeFreePoint':beforeFreePoint}
    DataRecordPack.DR_Freepoint(curPlayer, "AddPointOpen", setFreePoint, addDataDict)
    curPlayer.SetFreePoint(setFreePoint)
    GameWorld.DebugLog('    加点功能开启处理  beforeFreePoint=%s,curLV=%s, setFreePoint=%s'%(beforeFreePoint, curLV, setFreePoint), curPlayer.GetID())
    return
#---------------------------------------------------------------------
## 功能模块战斗力类
@@ -3338,6 +3402,8 @@
class ModuleFightPower():
    
    __AttrName = "%s" # 参数为ChConfig.Def_Calc_AllAttrType_MAX对应所有属性列表索引
    __AttrNameNoline = "Noline_%s" # 参数为ChConfig.Def_Calc_AllAttrType_MAX对应所有属性列表索引
    __NolineAttrList = [ChConfig.TYPE_Calc_AttrSpeed] # 需要记录的非线性战斗属性
    
    ## 初始化
    #  @param self 类实例
@@ -3357,6 +3423,8 @@
#            if attrIndex == ChConfig.TYPE_Calc_SuperHit:
#                value = ChConfig.Def_SuperHitPercent # 默认最低暴击倍值
            setattr(self, self.__AttrName % attrIndex, value)
        for attrIndex in self.__NolineAttrList:
            setattr(self, self.__AttrNameNoline % attrIndex, 0)
        return
            
    ## 根据战斗属性列表设置计算战斗力属性
@@ -3367,6 +3435,12 @@
        # 设置本模块增加的线性战斗属性,非线性战斗属性增加的在刷属性时累加上去
        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
    
    ## 设置计算战斗力属性值
@@ -3408,6 +3482,7 @@
        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 = 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) # 宠物伤害百分比提升
@@ -3426,8 +3501,9 @@
        DamagePerPVPReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePerPVPReduce) * fpParam.GetCftDamagePerPVPReduce() # 伤害输出计算百分比PVP减少
        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) # 防护值吸收伤害比率
        #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攻击回血
@@ -3436,7 +3512,7 @@
        #其他需作为公式参数的系数
        AtkSpeedParameter = fpParam.GetCftAtkSpeed()
        LuckyHitParameter = fpParam.GetCftLuckyHit()
        #获取策划配置的表格
        FightpowerFormula = IpyGameDataPY.GetFuncCfg("FightpowerFormula")
        totalFightPower = eval(FormulaControl.GetCompileFormula("FightpowerFormula", FightpowerFormula))
@@ -3451,6 +3527,14 @@
        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
@@ -3740,7 +3824,7 @@
        #未达到升级经验
        if curTotalExp < lvUpNeedExp:
            return
        needSyncTalentPoint = False
        playerNeedDoLVUp = False
        curLV = curPlayer.GetLV()
        maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
@@ -3774,6 +3858,7 @@
                       
            # 记录玩家升级
            DataRecordPack.DR_PlayerUpgrade(curPlayer, curPlayer.GetLV(), GetPlayerTotalExp(curPlayer), lvUpNeedExp)
            DataRecordPack.Cache_FightPowerChangeInfo(curPlayer, ChConfig.PowerDownType_LVUP, {'lv':curLV})
            
            self.__DoLVUPAddPoint()  # 升级加点
            #self.__DoLvUpAddSkill()  # 升级加技能
@@ -3781,7 +3866,10 @@
            lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
            # 大师天赋点
            if lvIpyData:
                PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, lvIpyData.GetTalentPoint())
                addTalentPoint = lvIpyData.GetTalentPoint()
                if addTalentPoint:
                    needSyncTalentPoint = True
                    PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, addTalentPoint)
            
            EventShell.EventResponse_LVUp(curPlayer)  # 升级触发事件
            
@@ -3830,10 +3918,16 @@
            #    NotifyCode(curPlayer, "GeRen_liubo_127574")
            
            #===================================================================
            # 天赋点通知
            if needSyncTalentPoint:
                PlayerGreatMaster.Sync_GreatMasterFreeSkillPoint(curPlayer)
            # 升级需要执行的游戏功能处理
            GameFuncComm.DoFuncOpenLogic(curPlayer)
            ChEquip.CalcEquips_OutOfPrint(curPlayer)    # 缓存绝版属性
            if aftLV%10 == 0:
                # 控制下刷新次数
                PlayerPet.CalcPetItemAddPlayerAttr(curPlayer)   # 宠物有随等级变化的技能
            self.RefreshPlayerAttrState(billboardFunc=PlayerBillboard.UpdatePlayerLVBillboard)
            #放在功能开启后面
            PlayerWorldAverageLv.UpdatePlayerWorldAverageLv(curPlayer)
@@ -3841,10 +3935,12 @@
            curPlayer.SetHP(curPlayer.GetMaxHP())
            if curPlayer.GetMaxMP() > 0:
                curPlayer.SetMP(curPlayer.GetMaxMP())
            FBLogic.OnPlayerLVUp(curPlayer)
            # 记录开服活动冲级数据
            OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_LV, curPlayer.GetLV())
            #神秘限购
            FunctionNPCCommon.MysticalShopOpen(curPlayer, befLV, aftLV)
        #不需要做升级任务, 设置玩家经验
        SetPlayerTotalExp(curPlayer, curTotalExp) 
        return
@@ -3999,6 +4095,7 @@
        PlayerFamilyTech.CalcFamilyTechAttr(curPlayer)
        PlayerEquipDecompose.RefreshEDAttr(curPlayer)
        PlayerDogz.RefreshDogzAttr(curPlayer)
        PlayerGatherSoul.RefreshGatherSoulAttr(curPlayer)
        self.RefreshAllState(isForce=True)
        GameWorld.DebugLog("End ReCalcAllState!!!")
        return
@@ -4122,6 +4219,7 @@
        #beforeAtkInterval = curPlayer.GetAtkInterval()
        beforeMaxHP = curPlayer.GetMaxHP()
        beforeMoveSpeedValue = GetSpeedValue(curPlayer)
        beforeMaxProDef = GetMaxProDef(curPlayer)
        #构建玩家刷新通知客户端字典, 缓存[索引, 数值]
        playerStateDict = {}
        for index in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
@@ -4316,6 +4414,9 @@
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, skillNoFightPowerAttrList[ChConfig.CalcAttr_Battle])
        #self.PrintAttr(curPlayer, "固定层级")
        
        #护盾值刷新
        self.__RefreshMaxProDef(beforeMaxProDef)
        # 【到此所有功能属性都已刷新处理完毕,复制一份 功能属性的刷新结果,用于BUFF属性单独刷新】
        EffGetSet.CopyPlayerFuncAttr(curPlayer)
        
@@ -4343,6 +4444,33 @@
        GameWorld.DebugLog("End RefreshPlayerAttrStateEx!!!")
        return True
    
    # 生命转化为防护值
    def __RefreshMaxProDef(self, beforeMaxProDef):
        curPlayer = self.__Player
        if GetProDefHPPer(curPlayer) == 0:
            return
        maxHP = curPlayer.GetMaxHP()
        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层属性,该层属性只会改变玩家最终属性,不会影响战力等
@@ -4620,14 +4748,16 @@
        mfpInfo.MFPCnt = len(mfpDataList)
        mfpInfo.MFPList = mfpDataList
        NetPackCommon.SendFakePack(curPlayer, mfpInfo)
        beforeFightPower = curPlayer.GetFightPower()
        curPlayer.SetFightPower(totalFightPower, False)
        if totalFightPower < beforeFightPower:
            DataRecordPack.DR_FightPowerChangeInfo(curPlayer, beforeFightPower)
        highestFightPower = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_Highest, 0,
                                                           ChConfig.Def_PDictType_FightPower)
        if totalFightPower > highestFightPower:
            NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Highest, totalFightPower,
                                 ChConfig.Def_PDictType_FightPower)
        GameWorld.DebugLog("总战力: %s, 历史最高战力: %s" % (totalFightPower, highestFightPower))
        GameWorld.DebugLog("总战力: %s, 历史最高战力: %s, beforeFightPower=%s" % (totalFightPower, highestFightPower, beforeFightPower))
        PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
        # 记录开服活动数据
        OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
@@ -4790,7 +4920,7 @@
                        }
        
        for i in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            if i in [ChConfig.TYPE_Calc_AttrHP, ChConfig.TYPE_Calc_AttrMP]:
            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)
@@ -5017,6 +5147,7 @@
    index = 0
    buffSkillIDList = []
    
    passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(curPlayer)
    while index < buffState.GetBuffCount():
        curBuff = buffState.GetBuff(index)
        #异常
@@ -5031,10 +5162,16 @@
            continue
        
        #BuffSkill.DoBuffDisApper(curPlayer, curBuff, tick)
        buffSkillIDList.append([curBuff.GetSkill().GetSkillID(), curBuff.GetOwnerID(), curBuff.GetOwnerType()])
        #buffSkillIDList.append([curBuff.GetSkill().GetSkillID(), curBuff.GetOwnerID(), curBuff.GetOwnerType()])
        buffSkillIDList.append(curBuff.GetSkill().GetSkillID())
        #GameWorld.DebugLog("死亡清理-----%s"%curBuff.GetSkill().GetSkillID())
        if passiveEff:
            passiveEff.DelBuffInfo(curBuff.GetSkill())
        #删除这个buff
        buffState.DeleteBuffByIndex(index)
    SkillShell.ClearBuffEffectBySkillIDList(curPlayer, buffState, buffSkillIDList)
    return
@@ -5541,6 +5678,9 @@
# SetExAttr1 ~ SetExAttr14(DWORD uiExAttr10, bool bNotifyAll = false, bool bNotifyGameServer = false)
# @param bNotifyAll: 是否广播所周围玩家,默认false,只会发给自己
# @param bNotifyGameServer: 是否同步GameServer,默认false
# SetExAttr15 ~ SetExAttr20(DWORD uiExAttr15)
#     15~20扩展属性同步封包:0309 选角登录简短信息、0434 周围玩家出现、0102 登录地图玩家信息;
#     同步前端及GameServer需要自己写通知,设置函数自身不带通知参数
#
# 发送0418包
# SendPropertyRefresh(int inputType, int inputValue, bool boardCast, bool includeSelf = true)
@@ -5548,6 +5688,8 @@
#
# ֪ͨGsmeServer; 
# SendGameServerRefreshState(int inputType, int inputValue)
# SetExAttr15 ~ 18 对应神兵类型等级,场景特效用
# 禁言 通知gameServer
def SetGMForbidenTalk(curPlayer, value):
@@ -5572,6 +5714,10 @@
def SetFBFuncLineID(curPlayer, funcLineID): return curPlayer.SetExAttr3(funcLineID, False, False)
def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3()
## 跨服状态: 0-非跨服状态,1-跨服状态
def GetCrossRealmState(curPlayer): return curPlayer.GetExAttr5()
def SetCrossRealmState(curPlayer, value): curPlayer.SetExAttr5(value, False, True)
## 铜钱点, 支持铜钱超20亿
def GetSilver(curPlayer): return curPlayer.GetExAttr6() * ChConfig.Def_PerPointValue + curPlayer.GetSilver()
def SetSilver(curPlayer, totalSilver):
@@ -5583,9 +5729,18 @@
        curPlayer.SetExAttr6(silverPoint)
    return
## 玩家今日已获得仙缘币
def GetTodayXianyuanCoin(curPlayer): return curPlayer.GetExAttr11()
def SetTodayXianyuanCoin(curPlayer, value): return curPlayer.SetExAttr11(value, False, True)
def AddTodayXianyuanCoin(curPlayer, addValue): return curPlayer.SetExAttr11(curPlayer.GetExAttr11() + addValue, False, True)
##VIP到期时间, 需要同步GameServer
def GetVIPExpireTime(curPlayer): return curPlayer.GetExAttr9()
def SetVIPExpireTime(curPlayer, expireTime): return curPlayer.SetExAttr9(expireTime, False, True)
##聊天气泡框
def GetChatBubbleBox(curPlayer): return curPlayer.GetExAttr10()
def SetChatBubbleBox(curPlayer, value): return curPlayer.SetExAttr10(value, False, True)
##获得玩家威望值
def GetPrestige(curPlayer): return 0
@@ -5782,7 +5937,6 @@
#  @param value: 威望值
#  @return: 
def SetMergeWarRank(curPlayer, value):
    curPlayer.SetExAttr10(value, True, True)
    return
    
@@ -5790,24 +5944,7 @@
#  @param curPlayer: 玩家实例
#  @return: 威望值
def GetMergeWarRank(curPlayer):
    return curPlayer.GetExAttr10()
## 设置玩家官爵星级
#  @param curPlayer: 玩家实例
#  @param value: 星级
#  @return:
def SetOfficeStar(curPlayer, value):
    curPlayer.SetExAttr11(value)
    return
## 获取玩家玩家官爵星级
#  @param curPlayer: 玩家实例
#  @return: 星级
def GetOfficeStar(curPlayer):
    return curPlayer.GetExAttr11()
    return 0
##获取可免费开启的格子数
# @param curPlayer 玩家对象
@@ -6398,17 +6535,17 @@
def GetMaxProDef(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrMaxProDef)
def SetMaxProDef(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrMaxProDef, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_MaxProDef, value, True) # 周围玩家需要通知
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_MaxProDef, value, False) # 周围玩家需要通知
#---生命上限换算为防护值的百分比----
def GetProDefHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefHPPer)
def SetProDefHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefHPPer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefHPPer, value, False)
    #curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefHPPer, value, False)
#---防护值吸收伤害比率----
def GetProDefAbsorb(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefAbsorb)
def SetProDefAbsorb(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefAbsorb, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefAbsorb, value, False)
    #curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefAbsorb, value, False)
    
#---宠物攻击提升值----
def GetPetMinAtk(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetMinAtk)
@@ -6416,11 +6553,13 @@
def GetPetMaxAtk(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetMaxAtk)
def SetPetMaxAtk(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetMaxAtk, value)
#---宠物伤害百分比提升----
def GetPetDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetDamPer)
def SetPetDamPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetDamPer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_PetDamPer, value, False)
#---宠物伤害百分比提升----移到GameObj下
#===============================================================================
# def GetPetDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetDamPer)
# def SetPetDamPer(curPlayer, value):
#    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetDamPer, value)
#    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_PetDamPer, value, False)
#===============================================================================
#---宠物技能伤害百分比提升----
def GetPetSkillAtkRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PetSkillAtkRate)
def SetPetSkillAtkRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PetSkillAtkRate, value)
@@ -6559,12 +6698,24 @@
def GetCalcAttrListValue(curPlayer, funcIndex):
    ## 获取功能点预先计算的所加属性值
    attrList = [{} for _ in range(4)]
    for attrIndex, attrDict in enumerate(attrList):
        for i in xrange(Def_MaxAddAttrTypeCnt):
            attrType = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i))
            if attrType == 0:
                break
            attrDict[attrType] = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i))
    if isinstance(funcIndex, int):
        funcIndexList = [funcIndex]
    elif isinstance(funcIndex, list):
        funcIndexList = funcIndex
    else:
        return attrList
    for funcIndex in funcIndexList:
        for attrIndex, attrDict in enumerate(attrList):
            for i in xrange(Def_MaxAddAttrTypeCnt):
                attrType = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i))
                if attrType == 0:
                    break
                attrValue = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i))
                if attrType in attrDict:
                    attrDict[attrType] = attrValue + attrDict[attrType]
                else:
                    attrDict[attrType] = attrValue
    return attrList
## 刷属性时累加功能事先计算好的属性值