hxp
2025-10-22 b6e2e296d9fd4fc7e503a852da6906a31f8e9088
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -17,9 +17,7 @@
import SkillShell
import ChConfig
import PlayerHorse
import PlayerTeam
import SkillCommon
import MirrorAttack
import GameMap
import FBLogic
import GameWorldProcess
@@ -35,12 +33,10 @@
import PlayerBillboard
import GameServerRefresh
import IPY_GameWorld
import PlayerGameWallow
import ChPyNetSendPack
import NetPackCommon
import DataRecordPack
import PlayerPrestigeSys
import PlayerActivity
import FBCommon
import PassiveBuffEffMng
import EventReport
@@ -49,29 +45,20 @@
import GameFuncComm
import IpyGameDataPY
import PyGameData
import PlayerMagicWeapon
import PlayerFeastTravel
import PlayerActTurntable
import GameLogic_SealDemon
import GameLogic_ZhuXianBoss
import GameLogic_CrossDemonKing
import PlayerVip
import PlayerCostRebate
import PlayerActLunhuidian
import PlayerActGarbageSorting
import GY_Query_CrossRealmReg
import PlayerTongTianLing
import FunctionNPCCommon
import PlayerGoldInvest
import CrossRealmPlayer
import CrossPlayerData
import ChNetSendPack
import PlayerAssist
import PlayerState
import PlayerGubao
import PlayerOnline
import PlayerTask
import PlayerMail
import PlayerLLMJ
import ChPlayer
import GameObj
@@ -424,10 +411,6 @@
        
    if not GameWorld.IsCrossServer() and GetCrossMapID(curPlayer):
        NotifyCode(curPlayer, "CrossMap10") 
        return False
    if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        GameWorld.Log("客户端自定义场景下无法传送!", curPlayer.GetPlayerID())
        return False
    
    return True
@@ -973,9 +956,6 @@
    #刷新技能剩余时间
    SkillCommon.RefreshAllSkillRemainTime(curPlayer, tick)
    
    #队伍玩家退出地图
    PlayerTeam.TeamPlayerLeaveMap(curPlayer, tick, isDisconnect)
    #退出采集
    NPCCommon.ClearCollectNPC(curPlayer)
@@ -1013,10 +993,8 @@
    playerID = curPlayer.GetPlayerID()
    if not isDisconnect:
        CrossPlayerData.ClearCrossSyncDataCache(curPlayer)
        PyGameData.g_fbBuyBuffTimeDict.pop(playerID, None)
    #清除地图玩家缓存
    PyGameData.g_playerReqEnterFBEx.pop(playerID, None)
    NPCCommon.ClearPriWoodPile(curPlayer)
    #移除地图缓存的境界难度玩家ID信息
    for playerIDList in PyGameData.g_realmDiffPlayerDict.values():
        if playerID in playerIDList:
@@ -1237,9 +1215,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:
        #默认回满血
@@ -1392,21 +1367,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)
@@ -1433,7 +1399,7 @@
    #进入副本通用检查
    fbIpyData = FBCommon.GetFBIpyData(mapID)
    fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID)
    sceneMapID = mapID if not fbLineIpyData else fbLineIpyData.GetMapID()
    sceneMapID = mapID #if not fbLineIpyData else fbLineIpyData.GetMapID()
    #过滤封包地图ID
    if not GameWorld.GetMap().IsMapIDExist(sceneMapID):
        GameWorld.ErrLog('###非法地图数据,sceneMapID: %s' % (sceneMapID), curPlayer.GetID())
@@ -1441,10 +1407,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)
@@ -1466,34 +1428,14 @@
            GameWorld.Log("非队长,无法发起进入组队副本请求!", curPlayer.GetPlayerID())
            return
        isSendToGameServer = True
    if isSendToGameServer or mapID in ChConfig.Def_MapID_SendToGameServer \
        or mapID in ReadChConfig.GetEvalChConfig("MapID_SendToGameServer"):
    if isSendToGameServer:
        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:
            enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)
        if mapID in ChConfig.Def_MapID_LineIDToPropertyID:
            enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbEnterCnt % mapID)
            extendParamList = [enterCnt]
        elif mapID in ChConfig.MirrorBattleMapIDList:
            reqInfoEx["sceneMapID"] = sceneMapID
            extendParamList = [reqInfoEx]
        #elif mapID in ChConfig.MirrorBattleMapIDList:
        #    reqInfoEx["sceneMapID"] = sceneMapID
        #    extendParamList = [reqInfoEx]
        SendToGameServerEnterFB(curPlayer, mapID, lineID, tick, extendParamList)
        return
    
@@ -1585,12 +1527,6 @@
            NotifyCode(curPlayer, "Carry_lhs_697674")
        return ShareDefine.EntFBAskRet_Sit
    
    if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        if isNotify:
            NotifyCode(curPlayer, "Carry_lhs_697674")
        GameWorld.Log("客户端自定义场景下无法进入副本!", curPlayer.GetPlayerID())
        return ShareDefine.EntFBAskRet_Other
    if playerAction in ChConfig.Def_Player_Cannot_TransState:
        #Carry_lhs_697674:您当前所处的状态不能进行传送!
        if isNotify:
@@ -1639,10 +1575,6 @@
# @return 无意义
# @remarks 刷新玩家时钟,切地图玩家时钟记录清空,处理相应逻辑
def RefreshPlayerTick(curPlayer):
    tick = GameWorld.GetGameWorld().GetTick()
    #防沉迷切线时间
    PlayerGameWallow.DoLogic_WallowOnlineTime(curPlayer, tick)
    return
@@ -1727,8 +1659,7 @@
    curPlayer.SetDict(ChConfig.Def_PlayerKey_TransTick, tick)
    
    mapID = FBCommon.GetRecordMapID(mapID)
    fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, funcLineID)
    sceneMapID = mapID if not fbLineIpyData else fbLineIpyData.GetMapID()
    sceneMapID = mapID #if not fbLineIpyData else fbLineIpyData.GetMapID()
    
    # 地图分流, 减少单地图压力
    FBMapShuntDict = ReadChConfig.GetEvalChConfig("FBMapShunt")
@@ -1888,8 +1819,8 @@
        return tagLineID
    tagLinePlayerCountDict = PyGameData.g_commMapLinePlayerCountDict[tagMapID] # 此分线包含所有分线,含未开放的及活动分线
    
    if bossID and tagMapID != ChConfig.Def_FBMapID_BossHome:
        tagLineID = 0 # Boss的话未分流前先强制1线,即为0
    #if bossID and tagMapID != ChConfig.Def_FBMapID_BossHome:
    #    tagLineID = 0 # Boss的话未分流前先强制1线,即为0
    playerID = curPlayer.GetPlayerID()
    playChangeLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_PlayChangeLineID)
    funcChangeLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FuncChangeLineID)
@@ -2551,6 +2482,20 @@
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
def GetUnXiantaoCntEquip(curPlayer):
    '''因为战锤对应装备是1个战锤可能对应多个装备掉落,所以分解装备的时候1个战锤需要支持可拆分
    所以需要支持小数存储,暂定以支持3位小数存储
    '''
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) / 1000.0
def AddUnXiantaoCntEquip(curPlayer, addCnt):
    unXiantaoCntEquip = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntEquip) + addCnt * 1000
    return NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip)
def SetUnXiantaoCntEquip(curPlayer, unXiantaoCntEquip):
    ## 保存装备未结算战锤数,保留3位小数
    # @param unXiantaoCntEquip: 实际的未结算数量,支持小数
    unXiantaoCntEquip = int(round(unXiantaoCntEquip, 3) * 1000) # 保留3为小数
    return NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntEquip, unXiantaoCntEquip)
##玩家是否有钱款
# @param curPlayer 玩家实例
# @param TYPE_Price ,货币类型
@@ -2607,7 +2552,7 @@
    #---钱不够 返回假如果需要提示的话 提示信息---
    if needMoneyCount < Price:
        if needNotify and notifyCode:
            NotifyCode(curPlayer, notifyCode)
            pass#NotifyCode(curPlayer, notifyCode)
        GameWorld.DebugLog("货币不足: TYPE_Price=%s, Price=%s, curMoneyCount=%s" % (TYPE_Price, Price, needMoneyCount))
        return False
    
@@ -2656,8 +2601,8 @@
        gold = curPlayer.GetGold() # 元宝
        
        if goldPaper + gold < Price: # 钱不够
            if needNotify:
                NotifyCode(curPlayer, "GoldErr")
            #if needNotify:
            #    NotifyCode(curPlayer, "GoldErr")
            return []
            
        if goldPaper >= Price: # 只用礼券就够了
@@ -2792,11 +2737,11 @@
    __PayMoneyAfter(curPlayer, type_Price, lostMoney, costType, infoDict, quantity, costVIPGold)
    
    #通知客户端失去金钱
    if isNotify:
        if type_Price == ShareDefine.TYPE_Price_PayCoin:
            NotifyCode(curPlayer, "LostMoney", [type_Price, str(round(lostMoney/100.0, 2))])
        else:
            NotifyCode(curPlayer, "LostMoney", [type_Price, lostMoney])
    #if isNotify:
    #    if type_Price == ShareDefine.TYPE_Price_PayCoin:
    #        NotifyCode(curPlayer, "LostMoney", [type_Price, str(round(lostMoney/100.0, 2))])
    #    else:
    #        NotifyCode(curPlayer, "LostMoney", [type_Price, lostMoney])
    return True
## 付款以后后续操作
@@ -2829,9 +2774,7 @@
    #银票支付
    elif type_Price == IPY_GameWorld.TYPE_Price_Silver_Paper:
        __PayMoneyAfterBySilverPaper(curPlayer, price)
    #活跃度处理
    PlayerActivity.OnPayMoneyActivity(curPlayer, type_Price, price)
    #转盘活动
    PlayerActTurntable.OnPlayerUseGold(curPlayer, type_Price, price)
    #轮回殿
@@ -2841,8 +2784,7 @@
        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)
        AddUnXiantaoCntEquip(curPlayer, price)
        # 累加未结算战锤 - 战利品
        chapterID = GetMainLevelNowInfo(curPlayer)[0]
        chapterIpyData = IpyGameDataPY.GetIpyGameData("MainChapter", chapterID)
@@ -2856,7 +2798,11 @@
                unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID)
                NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty + price)
                
        PlayerLLMJ.AddUseZhanchui(curPlayer, price)
        PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, price)
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_CutTree, price)
    unitPrice = price if quantity == 1 else int(math.ceil(price * 1.0 / quantity)) # 单价
    #reason_name = "Unknown" if not costType else costType
    reason_name = costType
@@ -2936,7 +2882,6 @@
    if costType not in ChConfig.CostRebate_DisableType:
        PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
        PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_UseGold, price)
        PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_UseGold, price)
    else:
        GameWorld.DebugLog("不计入消费活动的消费类型!costType=%s" % costType, curPlayer.GetPlayerID())
        
@@ -3018,7 +2963,7 @@
# @return 返回值真, 给钱成功
# @param isSysHint 是否系统提示(默认是)
# @remarks 玩家获得金钱
def GiveMoney(curPlayer, priceType, value, giveType=ChConfig.Def_GiveMoney_Unknown, addDataDict={}, isSysHint=True, isGiveBourseMoney=True):
def GiveMoney(curPlayer, priceType, value, giveType=ChConfig.Def_GiveMoney_Unknown, addDataDict={}, isSysHint=True, isGiveBourseMoney=True, notifyAward=False):
    if value == 0:
        return True
    
@@ -3031,6 +2976,9 @@
        msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "MoneyType":priceType, "Value":value, "GiveType":giveType, "AddDataDict":addDataDict}
        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_GiveMoney, msgInfo, [serverGroupID])
        return True
    if priceType == ShareDefine.TYPE_Price_FamilyExp:
        return PlayerFamily.AddFamilyExp(curPlayer, value)
    
    befMoney = GetMoney(curPlayer, priceType)
    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
@@ -3080,8 +3028,6 @@
            return
        updValue = min(ChConfig.Def_UpperLimit_DWord, curCurrency + value)
        SetPlayerCurrency(curPlayer, priceType, updValue)
        if priceType == ShareDefine.TYPE_Price_RealmPoint:
            PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_GetRealmPoint, value)
    else:
        GameWorld.ErrLog("金钱类型错误, priceType=%s,value=%s,giveType=%s" % (priceType, value, giveType), curPlayer.GetPlayerID())
        DataRecordPack.DR_GiveMoneyError(curPlayer, priceType, value, giveType, addDataDict)
@@ -3091,12 +3037,15 @@
    if priceType == ShareDefine.TYPE_Price_PayCoinDay:
        priceType = ShareDefine.TYPE_Price_PayCoin
        
    if isSysHint and priceType != ShareDefine.TYPE_Price_BourseMoney:
        #通知客户端得到金钱
        if priceType == ShareDefine.TYPE_Price_PayCoin:
            NotifyCode(curPlayer, "GetMoney", [priceType, str(round(value/100.0, 2))])
        else:
            NotifyCode(curPlayer, "GetMoney", [priceType, value])
    #if isSysHint and priceType != ShareDefine.TYPE_Price_BourseMoney:
    #    #通知客户端得到金钱
    #    if priceType == ShareDefine.TYPE_Price_PayCoin:
    #        NotifyCode(curPlayer, "GetMoney", [priceType, str(round(value/100.0, 2))])
    #    else:
    #        NotifyCode(curPlayer, "GetMoney", [priceType, value])
    if notifyAward:
        ItemControler.NotifyGiveAwardInfo(curPlayer, [], giveType, moneyInfo={priceType:value})
    __GiveMoneyAfter(curPlayer, priceType, value, giveType, addDataDict)
    
    if befMoney == 0:
@@ -3111,6 +3060,9 @@
    
    PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_GetMoney, value, [priceType])
    
    if priceType == ShareDefine.TYPE_Price_FamilyCoin:
        PlayerFamily.AddFamilyContrib(curPlayer, value) # 公会币同步增加公会贡献
    if priceType not in [IPY_GameWorld.TYPE_Price_Gold_Money, IPY_GameWorld.TYPE_Price_Gold_Paper, ShareDefine.TYPE_Price_PayCoin] \
        and giveType == ChConfig.Def_GiveMoney_Unknown:
        #GameWorld.DebugLog("该货币没有指定来源类型不记录!priceType=%s,giveType=%s" % (priceType, giveType))
@@ -3362,41 +3314,6 @@
    return IpyGameDataPY.GetFuncCfg("PKConfig", 2)
#---------------------------------------------------------------------
##获得玩家升级, 获得的属性点
# @param curPlayer 玩家实例
# @return 返回值, 获得的属性点
# @remarks 获得玩家升级, 获得的属性点
def GetLvUp_AddPoint(curPlayer):
    curPlayerID = curPlayer.GetID()
    curLV = curPlayer.GetLV() # 当前等级
    addPointDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1, {})
    addPoint = GameWorld.GetDictValueByRangeKey(addPointDict, curLV, 0)
    if addPoint == None:
        raise Exception('玩家获得升级属性点异常, curLV = %s PlayerID = %s' % (curLV, curPlayerID))
        return
    return int(addPoint+ GetFabaoAddPoint(curPlayer) + GetTitleAddExtraPoint(curPlayer))
def GetAllPointByLV(curPlayer):
    ##获取当前等级可得到属性点数
    openLV = GameFuncComm.GetFuncLimitLV(ShareDefine.GameFuncID_AddPoint)
    curLV = curPlayer.GetLV()
    if curLV < openLV:
        return 0
    # 初始点+(升级点+法宝效果)*称号效果倍数+境界点
    setFreePoint = IpyGameDataPY.GetFuncCfg("LVUPAddPoint", 2)
    fabaoAddPoint = GetFabaoAddPoint(curPlayer)
    titleAddPoint = GetTitleAddExtraPoint(curPlayer)
    addPointDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1, {})
    for rangLVs, point in addPointDict.items():
        if curLV < rangLVs[0]:
            continue
        setFreePoint += (point + fabaoAddPoint + titleAddPoint) * (min(curLV, rangLVs[1]) - rangLVs[0] + 1)
    #境界提升点数
    setFreePoint += curPlayer.GetOfficialRank() * IpyGameDataPY.GetFuncCfg("LVUPAddPoint", 3)
    return setFreePoint
def GetTitleAddExtraPoint(curPlayer):
    # 称号额外增加玩家每级获得的灵根点
@@ -3404,26 +3321,6 @@
    if titleID and curPlayer.GetDienstgradManager().GetDienstgrad(titleID):
        return IpyGameDataPY.GetFuncCfg("TitleAddPoint", 2)
    return 0
def GetFabaoAddPoint(curPlayer):
    #法宝额外增加玩家每级获得的灵根点
    mwID = IpyGameDataPY.GetFuncCfg('FabaoAddPoint', 1)
    if not PlayerMagicWeapon.GetIsActiveMagicWeapon(curPlayer, mwID, lv=1):
        return 0
    return IpyGameDataPY.GetFuncCfg('FabaoAddPoint', 2)
def DoAddPointOpen(curPlayer):
    '''加点功能开启'''
    beforeFreePoint = curPlayer.GetFreePoint()
    setFreePoint = GetAllPointByLV(curPlayer)
    curLV = curPlayer.GetLV()
    addDataDict = {'beforeFreePoint':beforeFreePoint}
    curPlayer.SetFreePoint(setFreePoint)
    DataRecordPack.DR_Freepoint(curPlayer, "AddPointOpen", setFreePoint, addDataDict)
    GameWorld.DebugLog('    加点功能开启处理  beforeFreePoint=%s,curLV=%s, setFreePoint=%s'%(beforeFreePoint, curLV, setFreePoint), curPlayer.GetID())
    return
    
#---------------------------------------------------------------------
###############################################################
@@ -3610,14 +3507,11 @@
            #aftFreePoint = curPlayer.GetFreePoint()
            if aftLV > befLV:
                curPlayer.SetLV(aftLV, False) # 这里不再通知GameServer
                PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_LVUp, aftLV - befLV)
                #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)
            PlayerGubao.DoGubaoAddFreePoint(curPlayer)
            
            # 升级需要执行的游戏功能处理
            GameFuncComm.DoFuncOpenLogic(curPlayer)
@@ -3630,12 +3524,6 @@
            #if curPlayer.GetMaxMP() > 0:
            #    curPlayer.SetMP(curPlayer.GetMaxMP())
            
            FBLogic.OnPlayerLVUp(curPlayer)
            # 记录开服活动冲级数据
            #OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_LV, curPlayer.GetLV())
            #神秘限购
            FunctionNPCCommon.MysticalLimitShopOpen(curPlayer, befLV, aftLV)
        #不需要做升级任务, 设置玩家经验
        SetPlayerTotalExp(curPlayer, curTotalExp) 
        return
@@ -3860,8 +3748,6 @@
        DoPlayerDead(curPlayer)
        
        GameObj.ClearPyPlayerState(curPlayer)
        MirrorAttack.OnPlayerDead(curPlayer)
        return
    
    
@@ -4298,7 +4184,6 @@
def Sync_ExpRateChange(curPlayer):
    totalExpRate = GetPlayerExpRate(curPlayer)
    fightExpRate = curPlayer.GetFightExpRate() # 系统及功能累加
    fightExpRate += PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_FightExpRate) # VIP加成
    fightExpRate += PlayerGoldInvest.GetAddFightExpRate(curPlayer)
    
    actExpRateInfo = PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_ExpRate, {})# 多倍经验活动加成
@@ -4307,11 +4192,11 @@
        if actExpIpyData and curPlayer.GetLV() >= actExpIpyData.GetLVLimit():
            fightExpRate += actExpIpyData.GetAddExpRate()
            
    if curPlayer.GetMapID() not in [ChConfig.Def_FBMapID_FamilyInvade]: #守卫人皇不加组队加成
        fightExpRate += curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TeamExpRate) # 组队
    #if curPlayer.GetMapID() not in [ChConfig.Def_FBMapID_FamilyInvade]: #守卫人皇不加组队加成
    #    fightExpRate += curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TeamExpRate) # 组队
    
    #地图多倍经验加成,默认是1倍不加成
    mapExpAddMultiple = max(0, FBCommon.GetAreaRewardMultiple(curPlayer) - 1)
    mapExpAddMultiple = 0
    fightExpRate += mapExpAddMultiple * ChConfig.Def_MaxRateValue
    
    if totalExpRate != fightExpRate:
@@ -4465,11 +4350,20 @@
    # @param wave: 第x波
    value = ComMainLevelValue(chapterID, levelNum, wave)
    SetMainLevelPassValue(curPlayer, value)
    if wave == 0:
        lvID = chapterID * 100 + levelNum
        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_MainLevel, lvID)
        PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_MainLevel)
        PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_MainLevel, lvID)
    return value
def GetMainLevelPassInfo(curPlayer):
    ## 获取主线关卡过关进度信息
    # @return: chapterID, levelNum, wave
    return GetMainLevelValue(GetMainLevelPassValue(curPlayer))
    chapterID, levelNum, wave = GetMainLevelValue(GetMainLevelPassValue(curPlayer))
    if not chapterID and not levelNum:
        chapterID, levelNum, wave = 1, 1, 0
        SetMainLevelPassValue(curPlayer, ComMainLevelValue(chapterID, levelNum, wave))
    return chapterID, levelNum, wave
## 主线关卡当前进度值 = 章节*10000+关卡编号*100+第x波
def GetMainLevelNowValue(curPlayer): return curPlayer.GetExAttr2()
@@ -4485,7 +4379,14 @@
def GetMainLevelNowInfo(curPlayer):
    ## 获取主线关卡当前进度信息
    # @return: chapterID, levelNum, wave
    return GetMainLevelValue(GetMainLevelNowValue(curPlayer))
    chapterID, levelNum, wave = GetMainLevelValue(GetMainLevelNowValue(curPlayer))
    if not chapterID and not levelNum:
        chapterID, levelNum, wave = 1, 1, 1
        SetMainLevelNowInfo(curPlayer, chapterID, levelNum, wave)
    if not wave:
        wave = 1
        SetMainLevelNowInfo(curPlayer, chapterID, levelNum, wave)
    return chapterID, levelNum, wave
def ComMainLevelValue(chapterID, levelNum, wave=0): return chapterID * 10000 + levelNum * 100 + wave
def GetMainLevelValue(value):
@@ -4493,6 +4394,13 @@
    levelNum = value % 10000 / 100
    wave = value % 100
    return chapterID, levelNum, wave
## 获取佩戴的称号ID
def GetTitleID(curPlayer): return curPlayer.GetExAttr3()
def SetTitleID(curPlayer, titleID):
    curPlayer.SetExAttr3(titleID, False, False)
    PlayerFamily.RefreshFamilyMember(curPlayer)
    return
## 协助目标玩家ID
def GetAssistTagPlayerID(curPlayer): return 0
@@ -4502,12 +4410,9 @@
def SetTeamCheckState(curPlayer, checkState): return
## 副本功能线路ID, 这里做db存储,防止在合并地图副本中掉线重上时前端无法加载正确的场景资源,登录加载场景时机为0102包
def SetFBFuncLineID(curPlayer, mapID, funcLineID):
    value = mapID * 1000 + funcLineID
    if value != curPlayer.GetExAttr3():
        curPlayer.SetExAttr3(value, False, True)
    return
def GetFBFuncMapID(curPlayer): return curPlayer.GetExAttr3() / 1000
def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3() % 1000
def GetFBFuncMapID(curPlayer): return 0
def GetFBFuncLineID(curPlayer): return 0
## 跨服状态所在地图ID: 0-非跨服状态,非0-跨服状态对应的地图ID
def GetCrossMapID(curPlayer): return curPlayer.GetExAttr5()
@@ -4515,16 +4420,6 @@
    curPlayer.SetExAttr5(value, False, True)
    if not value:
        CrossPlayerData.ClearCrossSyncDataCache(curPlayer)
    return
## 前端自定义场景
def GetCustomMapID(curPlayer): return curPlayer.GetExAttr14() / 1000
def GetCustomLineID(curPlayer): return curPlayer.GetExAttr14() % 1000
## 自定义场景后端判断已结算后需直接重置为0,防止前端没有退出场景直接下线导致数据没有重置,可能引发可以重复进
def SetCustomMap(curPlayer, mapID, lineID):
    value = mapID * 1000 + lineID
    if value != curPlayer.GetExAttr14():
        curPlayer.SetExAttr14(value, False, True)
    return
## 铜钱点, 支持铜钱超20亿
@@ -4547,8 +4442,8 @@
def SetVIPLVUpTime(curPlayer, lvUpTime): return
##聊天气泡框
def GetChatBubbleBox(curPlayer): return curPlayer.GetExAttr10()
def SetChatBubbleBox(curPlayer, value): return curPlayer.SetExAttr10(value, False, True)
def GetChatBox(curPlayer): return curPlayer.GetExAttr10()
def SetChatBox(curPlayer, value): return curPlayer.SetExAttr10(value, False, True)
##游戏充值支付代币
def GetPayCoinTotal(curPlayer): return GetPayCoin(curPlayer) + GetPlayerCurrency(curPlayer, ShareDefine.TYPE_Price_PayCoinDay)
@@ -4560,11 +4455,6 @@
    if payCoinDay > 0:
        PayMoney(curPlayer, ShareDefine.TYPE_Price_PayCoin, payCoinDay, "PayCoinOnDay")
    return
## 获取佩戴的称号ID
def GetTitleID(curPlayer):
    curDienstgradMgr = curPlayer.GetDienstgradManager()
    return curDienstgradMgr.GetCurGradID()
##伴侣
def GetCoupleID(curPlayer):
@@ -4616,13 +4506,27 @@
    ## 获取玩家在本地图中的境界难度层级,必须在境界地图且有选择境界难度才算,否则为默认0;该难度值同时也是视野层级
    return 0
##玩家退出仙盟信息: 主动离开次数*100 + 被踢次数*10  + 最后一次是否主动离开的
def GetLeaveFamilyInfo(curPlayer):
    # @return: 主动离开次数, 最后一次是否主动离开的
    value = curPlayer.GetExAttr12()
    leaveCnt = value / 100
    kickedCnt = value % 100 / 10
    lastVoluntarily = value % 10
    return leaveCnt, kickedCnt, lastVoluntarily
def SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, lastVoluntarily):
    value = min(9, leaveCnt) * 100 + min(9, kickedCnt) * 10 + lastVoluntarily
    curPlayer.SetExAttr12(value) # IPY_PlayerDefine.CDBPlayerRefresh_ExAttr12
    GameWorld.DebugLog("    SetLeaveFamilyInfo: value=%s" % (value))
    return value
##玩家离开仙盟时间(主动或被踢都算)
def GetLeaveFamilyTimeEx(curPlayer):return curPlayer.GetExAttr19()
def SetLeaveFamilyTimeEx(curPlayer, value):
    curPlayer.SetExAttr19(value)
    #curPlayer.SendGameServerRefreshState(ShareDefine.CDBPlayerRefresh_ExAttr19, value, 0)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ExAttr19, value, 0, False)
    return
    return value
##总战斗力,支持超过20E = 各模块战力总和
def GetFightPower(curPlayer): return curPlayer.GetFightPowerEx() * ChConfig.Def_PerPointValue + curPlayer.GetFightPower()
@@ -4639,9 +4543,7 @@
        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)
    #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
    #if beforeFightPower != totalFightPower:
    #    CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
    return
@@ -4788,6 +4690,13 @@
        return 0
    return lvIpyData.GetExp()
def GetOpenMaxLV():
    ## 获取游戏开放的最大等级
    maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    realmIpyData = ipyDataMgr.GetRealmByIndex(ipyDataMgr.GetRealmCount() - 1)
    return min(maxLV, realmIpyData.GetLVMax())
def GetPlayerMaxLV(curPlayer):
    ## 获取玩家实际可升的最大等级
    maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
@@ -4928,10 +4837,6 @@
# 血瓶恢复效果
def GetHPCureEnhance(curPlayer): return 0
# 仙盟徽章ID
def GetFamilyEmblemID(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyEmblemID)
def SetFamilyEmblemID(curPlayer, emblemID): NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyEmblemID, emblemID)
# 仙盟职位,使用 GetReceivedSalary,因为FamilyMemberLV没有入库
def GetFamilyMemberLV(curPlayer): return curPlayer.GetReceivedSalary()
def SetFamilyMemberLV(curPlayer, fmLV):
@@ -4994,10 +4899,11 @@
        
    if value == 0:
        curPlayer.NomalDictDelProperty(key, dType)
        return
        return 0
    # 2^31 - 1
    curPlayer.NomalDictAddProperty(key, min(value, ChConfig.Def_UpperLimit_DWordEx), dType)
    return
    value = max(0, min(value, ChConfig.Def_UpperLimit_DWordEx))
    curPlayer.NomalDictAddProperty(key, value, dType)
    return value
## 通知祝福值
def Sync_BlessValue(curPlayer, blessType, value, multiple=0):