#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------
##@package PlayerControl
# @todo: Íæ¼Ò¿ØÖÆÆ÷
#
# @author Alee
# @date 2010-02-20 16:30
# @version 1.0
#
#---------------------------------------------------------------------
#"""Version = 2017-07-17 15:00"""
#---------------------------------------------------------------------
import GameWorld
import ChEquip
import SkillShell
import ChConfig
import EventShell
import EffGetSet
import PlayerHorse
import PlayerTruck
import PlayerTrade
import PlayerTeam
import SkillCommon
import GameMap
import FBLogic
import GameWorldProcess
import NPCCommon
import ItemCommon
import ReadChConfig
import PlayerGMOper
import BuffSkill
import PetControl
import OperControlManager
import PlayerFamily
import ShareDefine
import PlayerBillboard
import GameServerRefresh
import IPY_GameWorld
import PlayerGameWallow
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 PlayerViewCacheTube
import PassiveBuffEffMng
import PlayerGameEvent
import EventReport
import PlayerGatherSoul
import PlayerGatherTheSoul
import PlayerSuccess
import PlayerPet
import PlayerGreatMaster
import ItemControler
import GameFuncComm
import IpyGameDataPY
import PlayerRune
import GameLogic_DuJie
import PyGameData
import PlayerMagicWeapon
import PlayerFeastTravel
import PlayerActTurntable
import GameLogic_SealDemon
import GameLogic_ZhuXianBoss
import GameLogic_CrossDemonKing
import PlayerTJG
import PlayerVip
import PlayerRefineStove
import PlayerFamilyTech
import PlayerFamilyZhenfa
import PlayerCostRebate
import PlayerActGarbageSorting
import GY_Query_CrossRealmReg
import PlayerTongTianLing
import PlayerCrossRealmPK
import FunctionNPCCommon
import IPY_PlayerDefine
import CrossRealmPlayer
import CrossPlayerData
import NPCHurtManager
import ChNetSendPack
import PlayerLianTi
import PlayerCoat
import PlayerAssist
import PlayerState
import QuestCommon
import PlayerDogz
import PlayerFaQi
import PlayerLove
import PlayerGubao
import PlayerShentong
import PlayerCharm
import PlayerTask
import ChPlayer
import GMShell
import GameObj
import random
import types
import math
import time
import json
#---------------------------------------------------------------------
#ÐÅÏ¢ÌáʾÁбí
NotifyCodeList = IPY_GameWorld.IPY_NotifyCodeList()
#buff×Ö¶ÎDieContinueλ±íʾ±êʶ
Def_Buff_Clear_Die = 0x1  # ËÀÍöÇå³ýbuff
Def_Buff_Clear_Disconnect = 0x2  # ÏÂÏßÇå³ýbuff
#---------------------------------------------------------------------
##¿Í»§¶Ë·¢ËÍÒÆ¶¯·â°ü¼ì²é
# @param curPlayer Íæ¼ÒʵÀý
# @param clientWorldTick ÉÏ´ÎÒÆ¶¯Ê±¼ä´Á
# @return ·µ»ØÖµÕæ, ¿ÉÒÔÒÆ¶¯
# @remarks ¿Í»§¶Ë·¢ËÍÒÆ¶¯·â°ü¼ì²é
def PlayerMoveCheckClientWorldTick(curPlayer, clientWorldTick, sendPack_PosX, sendPack_PosY):
    gameWorldTick = GameWorld.GetGameWorld().GetTick()
    Def_Max_Move_Tick = 5000
    if not curPlayer.GetSpeed():
        return False
    if abs(gameWorldTick - clientWorldTick) >= Def_Max_Move_Tick:
        curPlayer.Sync_ClientTick()
        #ʱ¼äÏà²î¹ý´ó£¬¿ÉÄÜÒòÍøÂçÒýÆð£¬À»Ø
        GameWorld.DebugLog("PlayerMoveCheckClientWorldTick -- ·þÎñÆ÷tick %s-¿Í»§¶Ë%sʱ¼äÏà²î¹ý´ó£¬¿ÉÄÜÒòÍøÂçÒýÆð£¬À»Ø" % (
                            gameWorldTick, clientWorldTick), curPlayer.GetID())
        return False
    
    if gameWorldTick - curPlayer.GetDictByKey("CheckTick") > 60000:
        # 1·ÖÖÓ¾ÀÕýÒ»´Îtick,ͬʱÓÃÓÚÕ½¶·ºÍÒÆ¶¯µÄ¼ì²é
        curPlayer.SetMoveCount(0)
        curPlayer.SetDict("CheckTick", gameWorldTick)
    
    lastMoveTick = curPlayer.GetClientMoveTick()
    if clientWorldTick < lastMoveTick:
        #and GameWorld.GetGameWorld().GetTick() - curPlayer.GetLoginTick() > 15000:
        #Íæ¼ÒµÇÈëʱ¼ä´óÓÚ15Ãë, ²Å»áÌß³öÍæ¼Ò
        #2009.4.16. bug:
        #Íæ¼ÒÇл»µØÍ¼, ·þÎñÆ÷»º´æ×ß··â°ü, µ½´ïеØÍ¼, »º´æÖеķâ°üÊÕµ½, ½á¹ûÌß³öÁËÍæ¼Ò
        GameWorld.DebugLog('---clientWorldTick < lastMoveTick: %s, TickÌ«Âý' % curPlayer.GetAccID())
        #curPlayer.Kick(IPY_GameWorld.disTickError)
        errCnt = curPlayer.GetMoveCount()
        curPlayer.SetMoveCount(errCnt + 1)
        if errCnt > 5:
            return False
    
    # ÑéÖ¤Á½´Îtick¼ä¿ÉÄܲúÉúµÄ×ø±ê²î
    dist = GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), sendPack_PosX, sendPack_PosY)
    canMoveDist = math.ceil((clientWorldTick - lastMoveTick) / float(curPlayer.GetSpeed())) + 2
    #if clientWorldTick - curPlayer.GetPlayerAttackTick() < GetAtkInterval(curPlayer):
    #    # ¹¥»÷²úÉúµÄÎ»ÒÆ¿ÉÄÜÒòΪ¹¥»÷ËÙ¶È¸Ä±ä¶ø±ä¿ì£¬¹¥»÷ÆÚ¼äµÄÒÆ¶¯°üÔÊÐí¶àÒÆ¶¯1Ã×µÄËÙ¶È
    #    canMoveDist += 2
        
    if dist > canMoveDist:
        GameWorld.DebugLog("¾àÀë²î%s ×ø±êS/C:%s---ÑéÖ¤Á½´Îtick¼ä¿ÉÄܲúÉúµÄ×ø±ê²î%s %s - %s" % (dist, [curPlayer.GetPosX(),
                            curPlayer.GetPosY(), sendPack_PosX, sendPack_PosY], canMoveDist, clientWorldTick, lastMoveTick))
        errCnt = curPlayer.GetMoveCount()
        curPlayer.SetMoveCount(errCnt + 1)
        if errCnt > 5:
            return False
    
    #ʱ¼ä²î
#    curPlayer.UpdatePosByTick(gameWorldTick - clientWorldTick + gameWorldTick)
    #curPlayer.UpdatePos()
    return True
# notifyCnt ´ú±í¹ã²¥ÖÜÎ§Íæ¼ÒµÄÊýÁ¿£¬0Ϊȫ²¿¹ã²¥ -1Ϊָ¶¨ÁбíËæ»ú£¬ ÆäËûÊý×ÖΪָ¶¨Ö¸
def PyNotifyAll(curPlayer, sendPack, notifySelf=True, notifyCnt=0):
    if notifyCnt == -1:
        notifyCnt = 8
    #GameWorld.DebugLog("PyNotifyAll %s"%notifyCnt)
    curPlayer.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength(), notifySelf, notifyCnt)
    
    
#---------------------------------------------------------------------
##Ö´ÐÐÍæ¼ÒÔÚÕϰµãÂß¼
# @param curPlayer Íæ¼ÒʵÀý
# @return ²¼¶ûÖµ, FlaseÎªÍæ¼Ò²»ÔÚÕϰµãÖÐ
# @remarks Ö´ÐÐÍæ¼ÒÔÚÕϰµãÂß¼
def DoLogic_PlayerInBarrierPoint(curPlayer):
    curPlayerPosX = curPlayer.GetPosX()
    curPlayerPosY = curPlayer.GetPosY()
    curPlayerID = curPlayer.GetID()
    
    #---Íæ¼Ò²»ÔÚÕϰµãÖÐ---
    if GameWorld.GetMap().CanMove(curPlayerPosX, curPlayerPosY):
        return False
    
    #---Íæ¼ÒÔÚÕϰµãÖÐ---
    
    #ÔÚÕϰµã¸½¼þ2¸ñѰÕÒºÏÊÊλÖÃ
    curFindPos = GameMap.GetEmptyPlaceInArea(curPlayerPosX, curPlayerPosY, 3)
    curFindPosX = curFindPos.GetPosX()
    curFindPosY = curFindPos.GetPosY()
    
    #Íæ¼ÒÎÞ·¿É×ß
    if curFindPosX == curPlayerPosX and curFindPosY == curPlayerPosY:
        curPlayer.StopMove()
#===============================================================================
#            playerControl = PlayerControl(curPlayer)
#            playerControl.SetToBornPlace()
#===============================================================================
        GameWorld.Log("Íæ¼ÒÎÞ·¿É×ß, ´ò»ØÖØÉúµã!(%d,%d)" % (curPlayerPosX, curPlayerPosY), curPlayerID)
    #ÕϰµãÖܱ߿ÉÒÔÒÆ¶¯, ½«Íæ¼ÒÖÃλ
    else:
        curPlayer.ResetPos(curFindPosX, curFindPosY)
        curPlayer.StopMove()
        GameWorld.Log("Íæ¼ÒÕ¾ÔÚÕϰµãÖÐ, Í£Ö¹ÒÆ¶¯ (%d,%d)" % (curPlayerPosX, curPlayerPosY), curPlayerID)
        
    return True
#---------------------------------------------------------------------
## ÏûÏ¢Ìáʾ
#  @param curPlayer ÌáʾµÄÍæ¼Ò
#  @param msgMark ÌáʾÐÅÏ¢Mark
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @return ÎÞ·µ»ØÖµ
#  @remarks 
def NotifyCode(curPlayer, msgMark, msgParamList=[]):
    if curPlayer == None:
        GameWorld.ErrLog('NotifyCode Player = None')
        return
      
    curPlayer.NotifyCode(msgMark, __GetNotifyCodeList(msgParamList))
    return
    
## ÊÀ½ç¹ã²¥
#  @param country ÌáʾµÄ¹ú¼Ò
#  @param msgMark ÌáʾÐÅÏ¢Mark
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @param lineID:Ïß·ID£¨Ä¬ÈÏ0£¬±íʾȫ·þ¹ã²¥£©
#  @param mergeMinOSD ¸ÃÌáʾÕë¶Ô¿ç·þ×Ó·þÓÐЧµÄ×îС¿ª·þÌì, >=0ʱÓÐÏÞÖÆ
#  @param mergeMaxOSD ¸ÃÌáʾÕë¶Ô¿ç·þ×Ó·þÓÐЧµÄ×î´ó¿ª·þÌì, >=0ʱÓÐÏÞÖÆ
#  @param mergeMapInfo ¸ÃÌáʾËùÊôµÄ¿ç·þ»î¶¯µØÍ¼ÐÅÏ¢, Ö÷ÒªÓÃÓÚ²»Í¬×Ó·þ¶ÔÓ¦Ëù¿çµÄ»î¶¯µØÍ¼ID
#  @return ÎÞ·µ»ØÖµ
def WorldNotify(country, msgMark, msgParamList=[], lineID=0, mergeMinOSD=-1, mergeMaxOSD=-1, mergeMapInfo=[]):
    GameWorld.GetPlayerManager().BroadcastCountry_NotifyCode(country, 0, msgMark, __GetNotifyCodeList(msgParamList), lineID)
    return
def GetCrossWorldNotifyInfo(country, msgMark, msgParamList=[]):
    return {"Type":ShareDefine.CrossNotify_World, "Params":[country, msgMark, msgParamList]}
def GetCrossFamilyNotifyInfo(familyID, msgMark, msgParamList=[]):
    return {"Type":ShareDefine.CrossNotify_Family, "Params":[familyID, msgMark, msgParamList]}
def CrossNotify(serverGroupIDList, crossNotifyList):
    ''' ¿ç·þ¹ã²¥ÐÅÏ¢Ìáʾ£¬Ö§³Öͬ²½¶àÌõ£¬Í¬Ê±Ò²½¨Òé¶àÌõÒ»Æðͬ²½
    @param serverGroupIDList: ÐèҪͬ²½µ½µÄÄ¿±ê·þÎñÆ÷×éIDÁбí
    @param crossNotifyList: ÐÅÏ¢ÌáʾÁÐ±í£¬Í¨¹ý GetCrossWorldNotifyInfo GetCrossFamilyNotifyInfo º¯Êý»ñµÃ·µ»ØÖµÌí¼Óµ½Áбí
    '''
    sendMsg = str([serverGroupIDList, crossNotifyList])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CrossNotify", sendMsg, len(sendMsg))
    return
#---------------------------------------------------------------------
## ¼Ò×å¹ã²¥
#  @param familyID ÌáʾµÄ¼Ò×åID
#  @param msgMark ÌáʾÐÅÏ¢Mark
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @return ÎÞ·µ»ØÖµ
#  @remarks 
def FamilyNotify(familyID, msgMark, msgParamList=[]):
    GameWorld.GetPlayerManager().BroadcastCountry_NotifyCode(0, familyID, msgMark, __GetNotifyCodeList(msgParamList))
    return
#---------------------------------------------------------------------
##±¾µØÍ¼ÄÚµÄ֪ͨ
#  @param msgMark ÌáʾÐÅÏ¢Mark
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @return ÎÞ·µ»ØÖµ
#  @remarks 
def FBNotify(msgMark, msgParamList=[]):
    GameWorld.GetMapCopyPlayerManager().BroadcastFB_NotifyCode(msgMark, __GetNotifyCodeList(msgParamList))
    return
def FBFactionNotifySelf(faction, msgMark, msgParamList=[]):
    ## ¸±±¾×Ô¼ºÕóÓª¹ã²¥
    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
        curPlayer = copyMapPlayerManager.GetPlayerByIndex(i)
        if curPlayer == None or curPlayer.IsEmpty():
            continue
        if curPlayer.GetFaction() == faction:
            NotifyCode(curPlayer, msgMark, msgParamList)
    return
def FBFactionNotifyOther(faction, msgMark, msgParamList=[]):
    ## ¸±±¾ÆäËûÕóÓª¹ã²¥
    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
        curPlayer = copyMapPlayerManager.GetPlayerByIndex(i)
        if curPlayer == None or curPlayer.IsEmpty():
            continue
        if curPlayer.GetFaction() != faction:
            NotifyCode(curPlayer, msgMark, msgParamList)
    return
def FBFactionNotify(faction, selfMsgMark, selfMsgParamList, otherMsgMark, otherMsgParamList):
    ## ¸±±¾¹ã²¥×Ô¼º¼°ÆäËûÕóÓª£¬Çø·Ö¹ã²¥ÐÅÏ¢
    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
    for i in xrange(copyMapPlayerManager.GetPlayerCount()):
        curPlayer = copyMapPlayerManager.GetPlayerByIndex(i)
        if curPlayer == None or curPlayer.IsEmpty():
            continue
        if curPlayer.GetFaction() == faction:
            NotifyCode(curPlayer, selfMsgMark, selfMsgParamList)
        else:
            NotifyCode(curPlayer, otherMsgMark, otherMsgParamList)
    return
## ¶ÓÎé¹ã²¥
#  @param teamID ¶ÓÎéID
#  @param msgMark ÌáʾÐÅÏ¢Mark
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @return ÎÞ·µ»ØÖµ
def TeamNotify(teamID, msgMark, msgParamList=[]):
    if teamID == 0:
        return
    
    sendMsg = '("%s", %s)' % (msgMark, msgParamList)
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, teamID, 'TeamNotify', sendMsg, len(sendMsg))
    return
#---------------------------------------------------------------------
def SendMailBatch(mailTypeKey, batchPlayerIDList, batchAddItemList=[], batchParamList=[], batchGold=[], batchGoldPaper=[], batchSilver=[], batchDetail=[], moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
    '''ÅúÁ¿·¢ËÍÓʼþ, ÓÃÓÚ˲¼äÐèÒª·¢ËͶà·â£¨´óÁ¿£©ÓʼþµÄ£¬±ÈÈçһЩ¹«¹²¸±±¾»î¶¯µÈ½áËãʱ
    @param mailTypeKey: ÓʼþÄ£°åkey
    @param batchPlayerIDList: [playerIDList, playerIDList, ...]
    @param batchAddItemList: [addItemList, addItemList, ...]
    @param batchParamList: [paramList, paramList, ...]
    @param batchGold: [batchGold, batchGold, ...]
    @param batchGoldPaper: [batchGoldPaper, batchGoldPaper, ...]
    @param batchSilver: [batchSilver, batchSilver, ...]
    @param batchDetail: [¼Ç¼ÓʼþÁ÷ÏòÓÃ, ...]
    @param moneySource: »õ±ÒÀ´Ô´
    '''
    
    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
    for i, playerIDList in enumerate(batchPlayerIDList):
        for playerID in playerIDList[::-1]:
            curPlayer = copyMapPlayerManager.FindPlayerByID(playerID)
            if curPlayer and not curPlayer.GetGameServerInitOK():
                bAddItemList = [batchAddItemList[i]] if len(batchAddItemList) > i else []
                bParamList = [batchParamList[i]] if len(batchParamList) > i else []
                bGold = [batchGold[i]] if len(batchGold) > i else []
                bGoldPaper = [batchGoldPaper[i]] if len(batchGoldPaper) > i else []
                bSilver = [batchSilver[i]] if len(batchSilver) > i else []
                bDetail = [batchDetail[i]] if len(batchDetail) > i else []
                AddUnLoginOKPlayerMailCache(playerID, "ByMailTemplate", [mailTypeKey, bAddItemList, bParamList, bGold, bGoldPaper, bSilver, bDetail, moneySource, crossMail])
                playerIDList.pop(playerIDList.index(playerID))
                continue
            
    msgInfo = str([mailTypeKey, batchPlayerIDList, batchAddItemList, batchParamList, batchGold, batchGoldPaper, batchSilver, batchDetail, moneySource, crossMail])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "SendMailBatch", msgInfo, len(msgInfo))
    GameWorld.Log("SendMailBatch %s, batchPlayerIDList=%s, batchAddItemList=%s, batchParamList=%s, batchGold=%s, batchGoldPaper=%s, batchSilver=%s" 
                  % (mailTypeKey, batchPlayerIDList, batchAddItemList, batchParamList, batchGold, batchGoldPaper, batchSilver))
    return
def SendMailByKey(mailTypeKey, playerIDList, addItemList, paramList=[], gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
    '''
    @param detail: ¼Ç¼ÓʼþÁ÷ÏòÓÃ
    '''
    if not mailTypeKey:
        mailTypeKey = ShareDefine.DefaultLackSpaceMailType
    
    content = "%s%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))
    SendMail("", content, 30, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource, crossMail)
    return
def SendCrossMail(serverGroupID, mailTypeKey, playerIDList, addItemList, paramList=[]):
    ## ·¢ËÍ¿ç·þÓʼþ
    if not serverGroupID:
        return
    dataMsg = {"MailTypeKey":mailTypeKey, "Player":playerIDList}
    if addItemList:
        dataMsg["Item"] = CombineMailItem(addItemList)
    if paramList:
        dataMsg["Param"] = paramList
    GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_SendMail, dataMsg, [serverGroupID])
    return
def SendEntireMail(mailTypeKey, getDays, limitLV, limitLVType, addItemList=[], paramList=[], \
                   gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail):
    ''' ·¢ËÍÈ«·þÓʼþ
    @param mailTypeKey: ÓʼþÄ£°åkey
    @param getDays: ÓÐЧÌìÊý
    @param limitLV: ÁìÈ¡×îµÍµÈ¼¶ÏÞÖÆ
    @param limitLVType: µÈ¼¶²»×ãµÄÉý¼¶ºóÊÇ·ñ¿ÉÁì 0-²»¿É£¬1-¿ÉÒÔ
    '''
    
    # ÓÐЧÌìÊýÏÞÖÆ
    if not mailTypeKey or getDays <= 0:
        return
    
    # ¿ç·þ·þÎñÆ÷²»ÔÊÐí·¢ËÍÓʼþ
    if GameWorld.IsCrossServer():
        return
    
    combineItemList = CombineMailItem(addItemList)
    cmdList = [mailTypeKey, getDays, limitLV, limitLVType, combineItemList, paramList, gold, goldPaper, silver, detail, moneySource]
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "SendEntireMail", '%s' % (cmdList), len(str(cmdList)))
    GameWorld.Log("·¢ËÍÈ«·þÓʼþ: %s,getDays=%s,limitLV=%s,limitLVType=%s,combineItemList=%s,paramList=%s,gold=%s,goldPaper=%s,silver=%s,detail=%s,moneySource=%s" % 
                  (mailTypeKey, getDays, limitLV, limitLVType, combineItemList, paramList, gold, goldPaper, silver, detail, moneySource))
    return
## ¹¦ÄÜ·¢·ÅÎïÆ·²¹³¥/½±ÀøÓʼþ
#  @param addItemList [(itemID, itemCnt, ÊÇ·ñÅÄÆ·), {»òÎïÆ·ÐÅÏ¢×Öµä}, ...]
#  @return
def SendMail(title, content, getDays, playerIDList, addItemList, gold=0, goldPaper=0, silver=0, detail="", moneySource=ChConfig.Def_GiveMoney_Mail, crossMail=False):
    if not playerIDList:
        return
    
#    if not addItemList:
#        return
    
    # ÓÐЧÌìÊýÏÞÖÆ
    if getDays <= 0:
        return
    
    # ¿ç·þ·þÎñÆ÷²»ÔÊÐí·¢ËÍÓʼþ
    if GameWorld.IsCrossServer() and not crossMail:
        return
    
    sendPlayerIDList = []
    copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()
    for playerID in playerIDList:
        curPlayer = copyMapPlayerManager.FindPlayerByID(playerID)
        if curPlayer and not curPlayer.GetGameServerInitOK():
            AddUnLoginOKPlayerMailCache(playerID, "ByMailContent", [title, content, getDays, addItemList, gold, goldPaper, silver, detail, moneySource])
            continue
        sendPlayerIDList.append(playerID)
        
    combineItemList = CombineMailItem(addItemList)
    cmdList = [title, content, getDays, sendPlayerIDList, combineItemList, gold, goldPaper, silver, detail, moneySource, crossMail]
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "SendMail", '%s' % (cmdList), len(str(cmdList)))
    return True
def AddUnLoginOKPlayerMailCache(playerID, cacheType, mailInfo):
    ''' Ìí¼ÓδµÇ¼³É¹¦µÄÍæ¼Ò¸öÈËÓʼþ·¢ËÍ»º´æ
    '''
    if playerID not in PyGameData.g_unLoginOKPlayerMailInfo:
        PyGameData.g_unLoginOKPlayerMailInfo[playerID] = []
    mailList = PyGameData.g_unLoginOKPlayerMailInfo[playerID]
    if [cacheType, mailInfo] in mailList:
        GameWorld.Log("###ÖØ¸´Ìí¼ÓGetGameServerInitOKδµÇ¼³É¹¦µÄÍæ¼Ò¸öÈËÓʼþ·¢ËÍ»º´æ! ²»Ìí¼Ó! mailCount=%s, mailInfo=%s" 
                      % (len(mailList), str(mailInfo)), playerID)
        return
    if len(mailList) >= 30: # ×ö¸öÏÞÖÆ£¬·ÀÖ¹³öÎÊÌâË¢Óʼþ
        GameWorld.Log("###ÏÞÖÆÌí¼ÓGetGameServerInitOKδµÇ¼³É¹¦µÄÍæ¼Ò¸öÈËÓʼþ·¢ËÍ»º´æ! ³¬³ö×î´ó¿ÉÌí¼ÓÊý£¬²»Ìí¼Ó! mailCount=%s, mailInfo=%s" 
                      % (len(mailList), str(mailInfo)), playerID)
        return
    mailList.append([cacheType, mailInfo])
    # curPlayer.GetGameServerInitOK()
    GameWorld.Log("Ìí¼ÓGetGameServerInitOKδµÇ¼³É¹¦µÄÍæ¼Ò¸öÈËÓʼþ·¢ËÍ»º´æ! µÈ´ý·¢ËÍ! mailCount=%s, mailInfo=%s" 
                  % (len(mailList), str(mailInfo)), playerID)
    return
def SendUnLoginOKPlayerMailCache(curPlayer):
    ## δµÇ¼³É¹¦µÄÍæ¼Ò¸öÈËÓʼþ·¢ËÍ»º´æ  - µÇ¼³É¹¦ºó´¦Àí
    if not curPlayer.GetGameServerInitOK():
        return
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_unLoginOKPlayerMailInfo:
        return
    mailList = PyGameData.g_unLoginOKPlayerMailInfo.pop(playerID)
    for cacheType, mailInfo in mailList:
        playerIDList = [playerID]
        GameWorld.Log("·¢ËÍδµÇ¼³É¹¦Ê±»º´æµÄ´ý·¢ËÍÓʼþ! cacheType=%s, mailInfo=%s" % (cacheType, str(mailInfo)), playerID)
        if cacheType == "ByMailContent":
            title, content, getDays, addItemList, gold, goldPaper, silver, detail, moneySource = mailInfo
            SendMail(title, content, getDays, playerIDList, addItemList, gold, goldPaper, silver, detail, moneySource)
        elif cacheType == "ByMailTemplate":
            mailTypeKey, bAddItemList, bParamList, bGold, bGoldPaper, bSilver, bDetail, moneySource, crossMail = mailInfo
            SendMailBatch(mailTypeKey, [playerIDList], bAddItemList, bParamList, bGold, bGoldPaper, bSilver, bDetail, moneySource, crossMail)
    return
def CombineMailItem(addItemList):
    ## ºÏ²¢ÓʼþÎïÆ·
    itemCountDict = {}
    combineItemList = [] # ºÏ²¢ºóµÄÎïÆ·Áбí
    for mailItem in addItemList:
        if isinstance(mailItem, dict):
            combineItemList.append(mailItem)
            continue
        
        if len(mailItem) < 3:
            continue
        
        itemID, itemCnt, isAuctionItem = mailItem[:3]
        appointID = mailItem[3] if len(mailItem) > 3 else 0
        if appointID:
            UserData = {ShareDefine.Def_CItemKey_AppointID:appointID}
            itemDict = {'ItemID':itemID, 'Count':itemCnt, 'IsAuctionItem':isAuctionItem, 'UserData':UserData}
            combineItemList.append(str(itemDict))
        elif isAuctionItem:
            combineItemList.append((itemID, itemCnt, isAuctionItem))
        else:
            key = (itemID, isAuctionItem)
            itemCountDict[key] = itemCountDict.get(key, 0) + itemCnt
            
    for key, itemCnt in itemCountDict.items():
        itemID, isAuctionItem = key
        combineItemList.append((itemID, itemCnt, isAuctionItem))
    return combineItemList
## ¹¹½¨ÏµÍ³Ìáʾ²ÎÊýÁбí
#  @param msgParamList ÐÅÏ¢²ÎÊýÁбí
#  @return ϵͳÌáʾ²ÎÊýÁбí IPY_NotifyCodeList
#  @remarks 
def __GetNotifyCodeList(msgParamList):
    #ÏûÏ¢ÌáʾÁбí, ÏÈÇåÔÚÌí¼Ó
    global NotifyCodeList
    NotifyCodeList.Clear()
    
    if not msgParamList:
        return NotifyCodeList
    
    for msg in msgParamList:
        itemPythonType = type(msg)
        
        if itemPythonType is types.IntType:
            #PythonÒªÑéÖ¤ÕûÐͺͳ¤ÕûÐÍ
            NotifyCodeList.AddInt(msg)
        elif itemPythonType is types.LongType:
            NotifyCodeList.AddStr(str(msg))
        else:
            NotifyCodeList.AddStr(msg)
    return NotifyCodeList
#---------------------------------------------------------------------
##»ñµÃÍæ¼Òµ±Ç°ÀۼƵÄÀëÏß·ÖÖÓÊý
# @param curPlayer Íæ¼ÒʵÀý
# @return ÀۼƵķÖÖÓÊý
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
def GetPlayerLeaveServerMinute(curPlayer):
    #µ±Ç°ÀëÏßʱ¼ä×Ö·û´«
    logoffTimeStr = curPlayer.GetLogoffTime()
    if logoffTimeStr == "" or logoffTimeStr == '0':
        return 0
    logoffTime = GameWorld.GetDateTimeByStr(logoffTimeStr)
    loginTime = GameWorld.GetDateTimeByStr(GameWorld.GetCurrentDataTimeStr())
    return GameWorld.GetDiff_Minute(loginTime, logoffTime)
##»ñµÃÍæ¼Òµ±Ç°ÀۼƵÄÀëÏßÃëÊý
# @param curPlayer Íæ¼ÒʵÀý
# @return ÀۼƵÄÃëÊý
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦
def GetPlayerLeaveServerSecond(curPlayer):
    #µ±Ç°ÀëÏßʱ¼ä×Ö·û´«
    logoffTimeStr = curPlayer.GetLogoffTime()
    if logoffTimeStr == "" or logoffTimeStr == '0':
        return 0
    logoffTime = GameWorld.GetDateTimeByStr(logoffTimeStr)
    loginTime = GameWorld.GetDateTimeByStr(GameWorld.GetCurrentDataTimeStr())
    diff_Time = loginTime - logoffTime
    #ÌìÊý * 24Сʱ * 60 ·ÖÖÓ + Ãë
    return diff_Time.days * 24 * 60 * 60 + diff_Time.seconds
##»ñµÃÍæ¼Òµ±Ç°Ê±¼ä¾àÀëÉÏ´ÎÀëÏßʱ¼äµÄÌìÊý
# @param curPlayer Íæ¼ÒʵÀý
# @return 
def GetPlayerLastLeaveServerPastDay(curPlayer):
    #µ±Ç°ÀëÏßʱ¼ä×Ö·û´«
    logoffTimeStr = curPlayer.GetLogoffTime()
    if logoffTimeStr == "" or logoffTimeStr == '0':
        return 0
    
    logoffTimeStr = logoffTimeStr.split()[0]
    loginTimeStr = GameWorld.GetCurrentDataTimeStr().split()[0]
    
    logoffTime = GameWorld.GetDateTimeByStr(logoffTimeStr, ChConfig.TYPE_Time_Format_Day)
    loginTime = GameWorld.GetDateTimeByStr(loginTimeStr, ChConfig.TYPE_Time_Format_Day)
    
    diffTime = loginTime - logoffTime
    
    return diffTime.days
    
#---------------------------------------------------------------------
## ¼ì²éÍæ¼Ò״̬ÊÇ·ñ¿ÉÒÔ´«ËÍ
#  @param curPlayer µ±Ç°Íæ¼Ò
#  @return ²¼¶ûÖµ
#  @remarks ¼ì²éÍæ¼Ò״̬ÊÇ·ñ¿ÉÒÔ´«ËÍ
def CheckPlayerTransport(curPlayer):
    #ËÀÍö²»¿ÉʹÓÃ
    if GameObj.GetHP(curPlayer) <= 0:
        return False
    
#    if curPlayer.GetPKValue() > 0:
#        #PK_lhs_161795
#        NotifyCode(curPlayer, "PK_lhs_161795")
#        return False
    
    #¼ì²éÍæ¼Ò״̬
    if not CheckTransState(curPlayer):
        return False
    
#    #Ñ£ÔÎʱ£¬²»¿É´«ËÍ
#    if curPlayer.GetAbnormalState() == IPY_GameWorld.sctFaint:
#        return False
    
    #=========================================================================================================
    # #ÀïÚ³µÖУ¬È˲»ÔÚïÚ³µÖÐÒ²²»ÄÜ´«ËÍ
    # if curPlayer.GetTruck() != None:
    #    NotifyCode(curPlayer, "HaveTruck_No_Trans")
    #    return False
    #=========================================================================================================
    
#    #±»¹¥»÷ʱºò, ÎÞ·¨Ê¹ÓÃ
#    if curPlayer.IsBattleState():
#        NotifyCode(curPlayer, "CannotAtk09")
#        return False
#    
#    #¶ÔÖÅÖÐ, ÎÞ·¨Ê¹ÓÃ
#    if curPlayer.GetIsConfronting():
#        NotifyCode(curPlayer, "CannotAtk09")
#        return False
    
    #¼ì²éÍæ¼ÒÊÇ·ñÔÚÆÕͨµØÍ¼
    if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
        #²¿·Ö¸±±¾ÔÊÐí´«ËͳöÈ¥
        if GameWorld.GetMap().GetMapID() not in IpyGameDataPY.GetFuncEvalCfg('DungeonDeliver', 1):
            NotifyCode(curPlayer, "Carry_lhs_844170") 
            return False
        
    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
##µØÍ¼ÌØÊâÏÞÖÆ¼ì²é, ×°±¸¼ì²é
# @param curPlayer
# @return bool
def CheckEquipCanTrans(curPlayer, destMapID):
    if destMapID != 10060:
        return True
    
    #Óгá°ò¿ÉÒÔÉÏÌì¿Õ
    playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
    curEquip = playerEquip.GetAt(IPY_GameWorld.retWing)
    if curEquip and not curEquip.IsEmpty():
        return True
    
    #GeRen_lhs_861048
    NotifyCode(curPlayer, "GeRen_lhs_861048", [destMapID])
    return False
#---------------------------------------------------------------------
##֪ͨ¿Í»§¶Ë, Íæ¼ÒLoading¿ªÊ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param prepareTime Loadingʱ¼ä
# @param prepareType LoadingÀàÐÍ
# @param prepareID LoadingNPCID, ĬÈÏΪ0, ²»ÉèÖÃ
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ֪ͨ¿Í»§¶Ë, Íæ¼ÒLoading¿ªÊ¼
# ÌØÊâ˵Ã÷ChangePlayerAction -> SetPlayerAction ÖÐ ÔÚÀÌõ״̬»á֪ͨ Sync_PrepareEnd£¬Ä¬ÈϽø¶ÈÌõÀàÐÍ
# Sync_PrepareEnd ֪ͨ0²ÅËã½ø¶ÈÌõ³É¹¦£¬ÆäËûΪʧ°Ü£¬×Ôµ÷ÓÃÂ߼ʱÇë×¢Òâ
def Sync_PrepareBegin(curPlayer, prepareTime, prepareType, prepareID=0):
    #ÖжÏÕ½¶·¶ÔÖÅ
    ExitPlayerConfronting(curPlayer)
    #´ò¶ÏÒÆ¶¯
    curPlayer.StopMove()
    #ÉèÖü¤»îÍæ¼Ò
    SetIsNeedProcess(curPlayer, True)
    #¿ªÊ¼Í¨ÖªLoading
    curPlayer.SetPrepareTime(prepareTime)
    curPlayer.SetPrepareState(prepareType)
    curPlayer.SetPrepareID(prepareID)
    curPlayer.Sync_PrepareBegin()
    
    #¿ÕÏÐת±äΪÆäËû״̬Ôòɾ³ýÓÐÏÞÎÞµÐBUFF
    tick = GameWorld.GetGameWorld().GetTick()
    DelLimitSuperBuff(curPlayer, tick)
    return
#---------------------------------------------------------------------
##Íæ¼Ò״̬¸Ä±ä
# @param curPlayer Íæ¼ÒʵÀý
# @param changeAction Çл»µÄ״̬
# @param forceChange ÊÇ·ñÇ¿ÖÆ×ª»»
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò״̬¸Ä±ä
def ChangePlayerAction(curPlayer, changeAction, forceChange=False):
    curPlayerAction = curPlayer.GetPlayerAction()
    
    if curPlayerAction == changeAction:
        return
    
    #״̬±ä¸üҪ֪ͨվÁ¢
    DoPlayerStand(curPlayer)
    
    #ÖжÏÕ½¶·¶ÔÖÅ
    if changeAction in ChConfig.Def_PlayerCancelConfronting:
        ExitPlayerConfronting(curPlayer)
    
    #ʼþ״̬²»Çл», ±ÜÃâ¶Ô»°¿¨×¡
    if curPlayerAction == IPY_GameWorld.paEvent and not forceChange:
        if changeAction in [IPY_GameWorld.paNull, IPY_GameWorld.paAttack]:
            GameWorld.DebugLog("²»Ç¿ÖÆ×ª»»×´Ì¬ %s" % changeAction, curPlayer.GetID())
            return
    
    # ²É¼¯Çл»
    if curPlayerAction == IPY_GameWorld.paPreparing:
        DoExitPreparing(curPlayer)
    
    curPlayer.SetPlayerAction(changeAction)
    
    if changeAction == IPY_GameWorld.paNull:
        return
    
    #¿ÕÏÐת±äΪÆäËû״̬Ôòɾ³ýÓÐÏÞÎÞµÐBUFF
    tick = GameWorld.GetGameWorld().GetTick()
    DelLimitSuperBuff(curPlayer, tick)
    
    return
##Í˳ö²É¼¯
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
def DoExitPreparing(curPlayer):
    NPCCommon.ClearCollectNPC(curPlayer)
    tagObj = curPlayer.GetActionObj()
    
    if tagObj == None:
        #ûÓÐÄ¿±ê
        GameWorld.Log("DoExitPreparing -> ûÓÐÄ¿±ê", curPlayer.GetPlayerID())
        return
            
    if tagObj.GetGameObjType() != IPY_GameWorld.gotNPC:
        #̸»°¶ÔÏó²»¶Ô
        GameWorld.Log("DoExitPreparing -> ²É¼¯¶ÔÏó²»¶Ô", curPlayer.GetPlayerID())
        return
    
    curNPC = GameWorld.GetNPCManager().GetNPCByIndex(tagObj.GetIndex())
    if curNPC == None:
        #ûÓÐÕâ¸öNPC
        GameWorld.Log("DoExitPreparing ->ûÓÐÕâ¸öNPC", curPlayer.GetPlayerID())
        return
    
    curNPC_HurtList = curNPC.GetPlayerHurtList()
    curNPC_HurtList.Clear()
    return
## Íæ¼Ò״̬¸Ä±ä(½Å±¾×Ô¶¨Òåö¾Ù)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param changeAction Çл»µÄ״̬
#  @return None
def ChangePyPlayerAction(curPlayer, changeAction):
    if GetPyPlayerAction(curPlayer, changeAction):
        #ÒѾÊÇÕâ¸ö״̬
        return
    
    state = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_PyPlayerAction)
    state = state | pow(2, changeAction)
    
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_PyPlayerAction, state)
    return
## »ñÈ¡ÊÇ·ñÓиÃ״̬
#  @param curPlayer Íæ¼ÒʵÀý
#  @param changeAction Çл»µÄ״̬
#  @return ÊÇ·ñÓиÃ״̬
def GetPyPlayerAction(curPlayer, action):
    receiveState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_PyPlayerAction)
    
    state = receiveState & pow(2, action) 
    #GameWorld.DebugLog("receiveState = %s, state = %s" % (receiveState, state))
    return state != 0
#---------------------------------------------------------------------
##ÉèÖÃÍæ¼ÒÊÇ·ñ¼¤»î
# @param curPlayer Íæ¼ÒʵÀý
# @param isNeedProcess ÊÇ·ñ¼¤»î
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ÉèÖÃÍæ¼ÒÊÇ·ñ¼¤»î
def SetIsNeedProcess(curPlayer, isNeedProcess):
    curPlayerIsNeedProcess = curPlayer.GetIsNeedProcess()
    
    if curPlayerIsNeedProcess == isNeedProcess:
        return
    
    curPlayer.SetIsNeedProcess(isNeedProcess)
    GameWorld.GodLog(curPlayer, 'ÉèÖÃÍæ¼ÒÊÇ·ñ¼¤»î:%s' % isNeedProcess)
    return
#---------------------------------------------------------------------
##Íæ¼ÒÊÇ·ñÔÚÕ½¶·×´Ì¬.
# @param curPlayer Íæ¼ÒʵÀý
# @return ²¼¶ûÖµ
# @remarks Íæ¼ÒÊÇ·ñÔÚÕ½¶·×´Ì¬
def IsPlayerInFight(curPlayer):
#    #Ö÷¶¯¶ÔÖÅÖÐ
#    if curPlayer.GetIsConfronting():
#        return True
    
    # ¹¥»÷ÖÐ
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
        return True
    
#    # ½øÈëÕ½¶·×´Ì¬
#    if curPlayer.IsBattleState():
#        return True
    return False
#---------------------------------------------------------------------
##×Ô¶¯½øÈëÕ½¶·¶ÔÖÅ //ÕâÀï²»¼ÓÏêϸÑéÖ¤
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ×Ô¶¯½øÈëÕ½¶·¶ÔÖÅ //ÕâÀï²»¼ÓÏêϸÑéÖ¤
def AutoEnterPlayerConfronting(curPlayer):
#    
#    if curPlayer.GetIsConfronting():
#        return
#    
#    actObj = curPlayer.GetActionObj()
#    
#    if not actObj:
#        return
#    
#    curPlayer.SetIsConfronting(True)
#    #֪ͨ¿Í»§¶Ë //0½øÈë;ÆäËûÍ˳ö
#    curPlayer.View_PlayerBattle(actObj.GetID(), actObj.GetGameObjType(), 0)
#    
#    #Ìí¼Ó²âÊÔÐÅÏ¢
#    GameWorld.GodLog(curPlayer, 'Server×Ô¶¯½øÈëÕ½¶·¶ÔÖųɹ¦')
    return
#---------------------------------------------------------------------
##//¶ÔÍâ½Ó¿Ú, Öж϶ÔÖÅ
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks //¶ÔÍâ½Ó¿Ú, Öж϶ÔÖÅ
def ExitPlayerConfronting(curPlayer):
#    if not curPlayer.GetIsConfronting():
#        return
#    
#    #Í˳ö¶ÔÖÅ
#    curPlayer.SetIsConfronting(False)
#    #֪ͨ¿Í»§¶Ë //0½øÈë;ÆäËûÍ˳ö
#    curPlayer.View_PlayerBattle(0, 0, 1)
#    
#    #Çå³ýÕ½³è³ðºÞ
#    PetControl.ClearFightPetAngry(curPlayer)
#    
#    #Ìí¼Ó²âÊÔÐÅÏ¢
#    GameWorld.GodLog(curPlayer, 'Í˳öÕ½¶·¶ÔÖųɹ¦')
    return
#---------------------------------------------------------------------
##²É¼¯´ò¶Ï
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ²É¼¯´ò¶Ï
def BreakPlayerCollect(curPlayer):
#    #²É¼¯¶¼²»´ò¶Ï
#    return
    
    if curPlayer.GetPlayerAction() != IPY_GameWorld.paPreparing:
        return
    #GameWorld.Log('    ²É¼¯´ò¶Ï curPlayer.GetPrepareState()=%s'%curPlayer.GetPrepareState())
    if curPlayer.GetPrepareState() not in [IPY_GameWorld.pstMissionCollecting, ShareDefine.Def_PstProduce]:
        #¼´²»ÊÇÈÎÎñ²É¼¯Ò²²»ÊÇÉú²ú²É¼¯
        return
    
    #¸±±¾Öв»´ò¶Ï
    #if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
    #    return
    
    tagObj = curPlayer.GetActionObj()
    
    if tagObj == None:
        #ûÓÐÄ¿±ê
        #GameWorld.Log("BreakPlayerCollect -> ûÓÐÄ¿±ê", curPlayer.GetPlayerID())
        return
            
    if tagObj.GetGameObjType() != IPY_GameWorld.gotNPC:
        #²É¼¯¶ÔÏó²»¶Ô
        #GameWorld.Log("BreakPlayerCollect -> ²É¼¯¶ÔÏó²»¶Ô", curPlayer.GetPlayerID())
        return
    
    curNPC = GameWorld.GetNPCManager().GetNPCByIndex(tagObj.GetIndex())
    if curNPC == None:
        #ûÓÐÕâ¸öNPC
        #GameWorld.Log("BreakPlayerCollect ->ûÓÐÕâ¸öNPC", curPlayer.GetPlayerID())
        return
    
    npcID = curNPC.GetNPCID()
    collectNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CollectNPC", npcID)
    if not collectNPCIpyData:
        return
    
    if not collectNPCIpyData.GetCanBreakCollect():
        return
    
    #È¡Ïû²É¼¯×´Ì¬
    ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
    
    if curPlayer.GetActionObj() != None:
        curPlayer.SetActionObj(None)
    return
#---------------------------------------------------------------------
##Íæ¼Ò´ò×ø
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò´ò×ø
def DoPlayerSit(curPlayer, tick):
    #ÒѾÔÚ´ò×ø×´Ì¬ÁË
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paSit:
        return
    
    #Í¨ÖªÍ£Ö¹ÒÆ¶¯
    curPlayer.StopMove()
    #¼¤»îÍæ¼Ò״̬, »Ø¸´CDÊÇ3Ãë, Íæ¼Ò´ôÖÍΪ5Ãë, Òª¼¤»îÒ»ÏÂ
    SetIsNeedProcess(curPlayer, True)
    #Íæ¼Ò×øÏÂ
    curPlayer.Sit()
    
    #ÉèÖÃÕæÆø¿ªÊ¼»Ö¸´Ê±¼ä
    #curPlayer.SetDict(ChConfig.Def_PlayerKey_SitForZhenQi, tick)
    #ÉèÖøßЧÁ·¹¦¿ªÊ¼Ê±¼ä
    #curPlayer.SetDict(ChConfig.Def_PlayerKey_EfficientSit, tick)
    return
#---------------------------------------------------------------------
##Íæ¼ÒÕ¾Æð
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÕ¾Æð
def DoPlayerStand(curPlayer):
    #²»ÔÚ´ò×ø×´Ì¬
    if curPlayer.GetPlayerAction() != IPY_GameWorld.paSit:
        return
    
    curPlayer.Stand()
    
    
    return
#---------------------------------------------------------------------
##Íæ¼Ò²¥·Å±íÇé
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò²¥·Å±íÇé
def DoPlayerShowPlayerFace(curPlayer, faceType):
    #Çå¿ÕÍæ¼Òµã»÷
    curPlayer.SetActionObj(None)
    #֪ͨÖжÏÕ½¶·¶ÔÖÅ
    ExitPlayerConfronting(curPlayer)
    #Í¨ÖªÍ£Ö¹ÒÆ¶¯
    curPlayer.StopMove()
    #֪ͨ¿Í»§¶Ë²¥·Å±íÇé
    curPlayer.View_ShowPlayerFace(faceType)
    return
#---------------------------------------------------------------------
##Íæ¼ÒËÀÍö
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒËÀÍö
def DoPlayerDead(curPlayer):
    
    #Í¨ÖªÍ£Ö¹ÒÆ¶¯
    curPlayer.StopMove()
    #Íæ¼ÒËÀÍö
    curPlayer.SetDead(curPlayer.GetDictByKey(ChConfig.Def_NPCDead_KillerID),
                      curPlayer.GetDictByKey(ChConfig.Def_NPCDead_KillerType))
    return
#---------------------------------------------------------------------
##Íæ¼ÒË¢ÐÂ×ø±ê
# @param curPlayer Íæ¼ÒʵÀý
# @param checkObj ¼ì²é¶ÔÏó
# @param posX Æðµã×ø±êX
# @param posY Æðµã×ø±êY
# @param canChangeClientPos ÊÇ·ñÖØÖõ½¿Í»§¶Ë×ø±êµã
# @return ·µ»ØÖµÕæ, ˢгɹ¦
# @remarks Íæ¼ÒË¢ÐÂ×ø±ê
def PlayerRefreshPos(curPlayer, checkObj, posX, posY, canChangeClientPos=True):
    if not curPlayer.GetMapLoadOK():
        #Ë¢ÐÂʧ°Ü
        #×¢Òâ: Ò»¶¨ÒªÅжÏ, ÒòΪÔÚÍæ¼ÒʹÓü¼ÄܵÄʱºò»áË¢ÐÂÕâÀï
        #Èç¹ûÍæ¼Ò¶ÁȡûÓгɹ¦, ¾Í²»´¦ÀíÕâ¸ö·â°ü
        GameWorld.Log('µØÍ¼Ã»ÓжÁÈ¡³É¹¦, Ë¢ÐÂʧ°Ü', curPlayer.GetPlayerID())
        return False
    
    if not curPlayer.GetSpeed():
        GameWorld.Log("ûÓÐËٶȲ»ÄÜË¢ÐÂ×ø±ê!", curPlayer.GetPlayerID())
        return False
    
    curMap = GameWorld.GetMap()
    
    #¼ì²éÍæ¼ÒͣϵÄ×ø±êÊÇ·ñÕýÈ·
    needResetPos = False
    
    if curMap.CanMove(posX, posY) != True:
        #ÌßÍæ¼ÒÏÂÏß
        #curPlayer.Kick(IPY_GameWorld.disPlayerPosError)
        #°ÑÍæ¼Ò´ò»ØÖØÉúµã
#        playerControl = PlayerControl(curPlayer)
#        playerControl.SetToBornPlace()
        #ÒÔÉÏ´¦ÀíÌ«¹ýÑϸñ, Ŀǰ²»Åж¨
        #-----------------------------------------
        #ÔÚÍæ¼ÒÖÜΧÕÒµ½Ò»¸ö¿É×ߵĵã, °ÑËû·Å¹ýÈ¥
        resultPos = GameMap.GetEmptyPlaceInArea(posX, posY, ChConfig.Def_DropItemDist)
        if resultPos.GetPosX() == posX and resultPos.GetPosY() == posY:
            #Íæ¼ÒÖØÖÃλÖÃʧ°Ü
            GameWorld.Log('Íæ¼ÒÖØÖÃλÖÃʧ°Ü, °ÑÍæ¼Ò´ò»ØÖØÉúµã posX = %s posY = %s' \
                          % (posX, posY), curPlayer.GetPlayerID())
#===============================================================================
#            playerControl = PlayerControl(curPlayer)
#            playerControl.SetToBornPlace()
#===============================================================================
            #ÔÝʱÍêÈ«ÐÅÈοͻ§¶Ë×ø±ê£¬±ÜÃâ±ßÔµ»¯ÎÞ·¨¹¥»÷ÎÊÌâ
            return False
        
        GameWorld.Log("×ø±ê´íÎ󣬼ì²éÍæ¼ÒͣϵÄ×ø±êÊÇ·ñÕýÈ· posX = %d, posY = %d, ÖØÖÃλÖÃ:posX = %d, posY = %d" \
                      % (posX, posY, resultPos.GetPosX(), resultPos.GetPosY()), curPlayer.GetPlayerID())
        
        posX = resultPos.GetPosX()
        posY = resultPos.GetPosY()
        
        #±ßÔµÕϰµãÈÿͻ§¶ËÐÐ×ߣ¬·þÎñ¶Ë¸Ä±äλÖò»Í¨Öª
        #needResetPos = True
        #checkObj.ResetPos(posX, posY)
    
    #µ±Ç°¶ÔÏó×ø±ê
    objPosX = checkObj.GetPosX()
    objPosY = checkObj.GetPosY()
#    objDestPosX = checkObj.GetDestPosX()
#    objDestPosY = checkObj.GetDestPosY()
#    objStartX = checkObj.GetStartPosX()
#    objStartY = checkObj.GetStartPosY()
    #¼ÆËãÍæ¼Ò·¢¹ýÀ´µÄֹͣλÖúͷþÎñÆ÷ÒÑÓÐ×ø±êµÄ¾àÀë
    dist = GameWorld.GetDist(posX, posY, objPosX, objPosY)
    
    #ÒÆ¶¯µÄÌØµã£º¿Í»§¶ËÒÆ¶¯Îª1Ã×С¼ä¸ô·¢°ü£¬·þÎñ¶ËµÄUpdatePos ¾³£ δִÐе¼ÖÂÎÞ·¨Òƶ¯£¬Òƶ¯ÐÐΪ±ä³É  __FixPlayerPos-¡·ChangePos¿ØÖÆ
    #Íâ²ãÒÆ¶¯tick ¿ØÖƼä¸ô·ÀÖ¹Íâ¹Ò°ü
    if dist <= 3:
        #µÚÒ»ÖÖÇé¿ö:¿Í»§¶ËºÍ·þÎñÆ÷¶Ë¾àÀë²î¾à·ûºÏÒªÇó
        #λÖÿÉÒÔ½ÓÊÜ
        __FixPlayerPos(checkObj, posX, posY, needResetPos, canChangeClientPos)
        return True
    else:
        #¾àÀëÆ«²îÌ«´ó£¬À»ØÎ»Öò»×öÌßÈËÂß¼
        needResetPos = True
        GameWorld.DebugLog('Client=(%s,%s), Server=(%s,%s), ²îÒì¾àÀë=%s' \
                     % (posX, posY, objPosX, objPosY, dist))
        posX = objPosX
        posY = objPosY
        __FixPlayerPos(checkObj, posX, posY, needResetPos, canChangeClientPos)
        return False
    
    # ʵ¼Ê´Ëº¯ÊýÔÚ¶Ô»°  ¹¥»÷ ÒÆ¶¯¶¼»á×ß½øÀ´Åж¨
    #===========================================================================
    # curPlayer.SetMoveCount(curPlayer.GetMoveCount() + 1)
    # if curPlayer.GetMoveCount() >= 10:
    #    curPlayer.SetMoveCount(0)
    #    curPlayer.SetMoveDistDiff(0)
    #    needResetPos = True
    #    
    # if curPlayer.GetMoveDistDiff() >= 30:
    #    curPlayer.SetMoveCount(0)
    #    curPlayer.SetMoveDistDiff(0)
    #    needResetPos = True
    #===========================================================================
    __FixPlayerPos(checkObj, posX, posY, needResetPos, canChangeClientPos)
    return True
#    curPlayer.SetMoveCount(curPlayer.GetMoveCount() + 1)
#    
#    #Def_PlayerMoveCheckClearCount:
#    #Íæ¼ÒÒÆ¶¯¶àÉÙ´ÎÇå¿ÕÕâ¸öÀۼƴíÎó        
#    if curPlayer.GetMoveCount() >= ReadChConfig.GetEvalChConfig('Def_PlayerMoveCheckClearCount'):
#        curPlayer.SetMoveCount(0)
#        curPlayer.SetMoveDistDiff(0)
#    
#    #¾àÀë(Æðµã-¿Í»§¶ËλÖÃ-·þÎñÆ÷¶ËλÖÃ-ÖÕµã)
#    severDist = GameWorld.GetDist(objPosX, objPosY, objDestPosX, objDestPosY)
#    severTotalDist = GameWorld.GetDist(objStartX, objStartY, objDestPosX, objDestPosY)
#    clientDist = GameWorld.GetDist(posX, posY, objDestPosX, objDestPosY)
#    
#    clientSlow = False
#    
#    if clientDist >= severDist and clientDist <= severTotalDist:
#        #·½Ïò
#        severDir = GameWorld.GetAngle(objStartX, objStartY, objDestPosX, objDestPosY) 
#        clientDir = GameWorld.GetAngle(posX, posY, objDestPosX, objDestPosY)
#    
#        clientSlow = True    
##===============================================================================
##        #2011-1-19 ´ËÖÖÇé¿öÒ²Òª¼ÆËãÎó²î
##        #Èç¹û½Ç¶È²î±ð10¶È, ÔòÈÏΪ¿ÉÒÔ½ÓÊÜ
##        dirDiff = 10
##        dirDiffValue = abs(severDir - clientDir)
##        
##        if dirDiffValue <= dirDiff:
##            #µÚ¶þÖÖÇé¿ö:·þÎñÆ÷±È¿Í»§¶Ë¿ì
##            #¿ÉÒÔ½ÓÊÜ
##            __FixPlayerPos(checkObj, posX, posY, needResetPos, canChangeClientPos)
##            return True
##===============================================================================
#    #·þÎñÆ÷±È¿Í»§¶ËÂý#ChConfig.Def_AcceptPlayerStopPlaceDist:
#    if dist > ReadChConfig.GetEvalChConfig('Def_AcceptPlayerStopPlaceDist'):
#        return False
#        #ÌßÍæ¼ÒÏÂÏß
#        if clientSlow:
#            GameWorld.ErrLog("³¬´óÎó²î, ¿Í»§¶Ë±È·þÎñÆ÷Âý %d" % dist, curPlayer.GetPlayerID())
#        else:
#            GameWorld.ErrLog("³¬´óÎó²î, ·þÎñÆ÷±È¿Í»§¶ËÂý %d" % dist, curPlayer.GetPlayerID())
#            #·þÎñÆ÷¶Ë±È¿Í»§¶ËÂý¿ÉÒÔ½ÓÊÜ
#            return False
#        
#        #GameWorld.GodLog(curPlayer, '³¬´óÎó²î, Ôݲ»´¦Àí, clientSlow = %s, dist = %s'%(clientSlow, dist))
#        
#        #³¬´óÎó²î·âÍ£Õ˺Åʱ¼ä
#        closeAccIDTime = ReadChConfig.GetEvalChConfig('Def_BigErrorDistCloseAccTime')
#    
#        if closeAccIDTime > 0:
#            #³¬´óÎó²î·âÍ£Íæ¼Ò
#            PlayerGMOper.ClosePlayerByAccID(curPlayer, closeAccIDTime, 'BigErrorDist = %s Kick' % (dist))
#        else:
#            #³¬´óÎó²îÌß³öÍæ¼Ò
#            curPlayer.Kick(IPY_GameWorld.disPlayerMoveToFar)
#    
#        return False
#    
#    #ֹͣλÖÿɽÓÊÜ,µ±Ðè¼Ç¼
#    curMoveDistDiff = curPlayer.GetMoveDistDiff() + dist
#    curPlayer.SetMoveDistDiff(curMoveDistDiff)
#    
#    #ÐÂÔöÒÆ¶¯×ø±ê²îÖµDebugÌáʾÐÅÏ¢,·½±ã¿Í»§¶Ë²éѯ
#    GameWorld.GodLog(curPlayer, 'Client=(%s,%s), Server=(%s,%s), ÀÛ¼Ó¾àÀë=%s, ÀÛ¼Ó×ÜÖµ=%s' \
#                     % (posX, posY, objPosX, objPosY, dist, curPlayer.GetMoveDistDiff()))
#    
#    #Íæ¼ÒÒÆ¶¯100´Î¼ì²éÒ»´Î
#    if curPlayer.GetMoveCount() >= ReadChConfig.GetEvalChConfig('Def_PlayerMoveCheckCount'):
#        maxMoveDistDiff = ReadChConfig.GetEvalChConfig('Def_PlayerMoveCheckDist')
#        #2009/07/15 Òò¸±±¾ÀÈË˲¼ä¾àÀë¹ý´ó£¬¸±±¾Åж¨¾àÀëË«±¶
#        if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
#            maxMoveDistDiff = maxMoveDistDiff * 2
#        
#        if curMoveDistDiff >= maxMoveDistDiff:
#            return False
#            GameWorld.Log("Íæ¼ÒÒÆ¶¯´íÎó´ÎÊý = %s, ÒÆ¶¯ÀۼƾàÀë = %s, ÌßÍæ¼ÒÏÂÏß" \
#                          % (curPlayer.GetMoveCount(), curMoveDistDiff), curPlayer.GetPlayerID())
#            
#            closeAccIDTime = ReadChConfig.GetEvalChConfig('Def_MoveDistErrorCloseAccTime')
#            
#            if closeAccIDTime > 0:
#                PlayerGMOper.ClosePlayerByAccID(curPlayer, closeAccIDTime, 'MoveCheckKick, ErrDist = %s' \
#                                                % (curMoveDistDiff))
#            else:
#                curPlayer.Kick(IPY_GameWorld.disPlayerMoveAddUpError)
#
#            return False
#
#    #µÚ3ÖÖÇé¿ö:¼Ç¼²¢½ÃÕý×ø±ê
#    __FixPlayerPos(checkObj, posX, posY, needResetPos, canChangeClientPos)
#    return True
#---------------------------------------------------------------------
##½ÃÕýÍæ¼Ò×ø±ê
# @param checkObj ¼ì²éµÄ¶ÔÏó
# @param changePosX ½ÃÕýµÄ×ø±êX
# @param changePosY ½ÃÕýµÄ×ø±êY
# @param needResetServerPos  ÊÇ·ñ°´·þÎñÆ÷λÖÃÖØÖÃ
# @param needChangeClientPos ÊÇ·ñ°´¿Í»§¶ËλÖÃÖØÖÃ
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ½ÃÕýÍæ¼Ò×ø±ê
def __FixPlayerPos(checkObj, changePosX, changePosY, needResetServerPos, needChangeClientPos):
    #---°´·þÎñÆ÷λÖÃÖØÖÃ---
    if needResetServerPos:
        checkObj.ResetPos(changePosX, changePosY)
        return
    
    #---°´¿Í»§¶ËλÖÃÖØÖÃ---
    if needChangeClientPos:
        checkObj.ChangePos(changePosX, changePosY)
        return
    
    return
#---------------------------------------------------------------------
##ɱËÀÍæ¼ÒËùÓеÄÕÙ»½ÊÞËÀÍö
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ɱËÀÍæ¼ÒËùÓеÄÕÙ»½ÊÞËÀÍö
def KillPlayerSummonNPC(curPlayer):
    #½«Éæ¼°µ½C++ÖÐÁбíɾ³ýµÄ¹¦ÄÜ,ͳһ¸Ä³É -> ¸´ÖÆPyÁбíºó,È»ºó½øÐÐɾ³ýÂß¼ (ÒòWhileÓм¸Âʽ«µ¼ÖÂËÀËø)
    summon_List = []
    for index in range(curPlayer.GetSummonCount()):
        curSummonNPC = curPlayer.GetSummonNPCAt(index)
        summon_List.append(curSummonNPC)
    
    for summonNPC in summon_List:
        NPCCommon.SetDeadEx(summonNPC)    
    return
#---------------------------------------------------------------------
##¼ì²éÍæ¼ÒͨÓõÄ״̬ת»»
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÕæ, ÔÊÐíÇл»×´Ì¬
# @remarks ¼ì²éÍæ¼ÒͨÓõÄ״̬ת»»
def PlayerCanStateTransfer(curPlayer):
    curPlayerAction = curPlayer.GetPlayerAction()
    #Èç¹ûÍæ¼ÒÊÇ×øÏÂ״̬, ×Ô¶¯×ª»»ÎªÕ¾Á¢×´Ì¬
    #DoPlayerStand(curPlayer)
        
    return (curPlayerAction in ChConfig.Def_Player_Can_Transfer_State)
#------------------------------Íæ¼ÒÀ뿪·þÎñÆ÷µÄÂß¼------------------------------------
#---------------------------------------------------------------------
##ïÚ³µÏÂÏßÂß¼
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ïÚ³µÏÂÏßÂß¼
def __TruckPlayerDisconnect(curPlayer):
    return
    #ÔÚïÚ³µ
    if PlayerTruck.GetHaveAutoTruck(curPlayer):
        curPlayerTruck = curPlayer.GetTruck()
        curPlayerTruck.SetOwner(None)
        PlayerTruck.PlayerTruckDown(curPlayer, curPlayerTruck)
        
    return
#---------------------------------------------------------------------
##ÆïÂíÏÂÏßÂß¼
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ÆïÂíÏÂÏßÂß¼
def __RidingHorsePlayerDisconnect(curPlayer):
    #ÔÚÆïÂí
    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
        #Ö´ÐÐÏÂÂíÂß¼
        PlayerHorse.PlayerRideHorseDown(curPlayer, False)
        
    return
#---------------------------------------------------------------------
##Íæ¼ÒÏÂÏß/Íæ¼ÒÇл»µØÍ¼¹«ÓÃÂß¼
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÏÂÏß/Íæ¼ÒÇл»µØÍ¼¹«ÓÃÂß¼
def __PlayerLeaveServerLogic(curPlayer, tick, isDisconnect):
    #¸øÓèÍæ¼Ò²¹³¥
    #PlayerExpiation.GivePlayerExpiation(curPlayer, tick)
    
    #ÔËÐÐÀëÏßxml
    EventShell.EventResponse_OnLeaveMap(curPlayer)
    
    #Èç¹ûÍæ¼ÒÓÐæô³µ, °Ñæô³µµÄÖ÷ÈËÉèÖÃΪNone
    curPlayerTruck = curPlayer.GetTruck()
    
    if curPlayerTruck != None:
        curPlayerTruck.SetOwner(None)
    #ˢм¼ÄÜÊ£Óàʱ¼ä
    SkillCommon.RefreshAllSkillRemainTime(curPlayer, tick)
    
    #Èç¹ûÔÚ½»Ò×״̬,È¡Ïû½»Ò×Ë«·½µÄ½»Ò×״̬²¢½â³ý½»Ò×À¸ÖÐÎïÆ·Ëø¶¨×´Ì¬
    PlayerTrade.LeaveTrade(curPlayer, 0)
    
    #¶ÓÎéÍæ¼ÒÍ˳öµØÍ¼
    PlayerTeam.TeamPlayerLeaveMap(curPlayer, tick, isDisconnect)
    #Í˳ö²É¼¯
    NPCCommon.ClearCollectNPC(curPlayer)
    #½áÊøÊ¼þ
    EventShell.DoExitEvent(curPlayer)
    #ÉèÖÃÍæ¼ÒµÄµØÍ¼Î»ÖÃ, Èç¹ûÊǸ±±¾, À뿪¸±±¾
#    ¸±±¾¹æÔò:
#    1. Ò»¸ö¶ÓÎéÖ»ÓÐÒ»¸ö¸±±¾, Èç¹ûÓжÓÔ±µÄ¸±±¾ºÍ¶ÓÎ鸱±¾²»Ò»ÖÂ, Ôò´Ó¸±±¾ÖÐÌß³ö´Ë¶ÓÔ±
#    2. Íæ¼ÒÏÂÏßÔÙÉÏ, ¾ÍÀ뿪¸±±¾
#    3. Èç¹ûûÓÐÍæ¼Ò´æÔÚ, ¸±±¾»ØÊÕ
    if GameWorld.GetMap().GetMapFBType() != 0:
        #À뿪¸±±¾
        fbIndex = GameWorld.GetGameWorld().GetCurGameWorldIndex()
        exitFBType = 1 if isDisconnect else 2
        PyGameData.g_lastExitFBType[fbIndex] = [exitFBType, tick]
        #GameWorld.DebugLog("Íæ¼ÒÀ뿪¸±±¾£ºfbIndex=%s,exitFBType=%s, %s" % (fbIndex, exitFBType, PyGameData.g_lastExitFBType), curPlayer.GetPlayerID())
        FBLogic.DoExitFBLogic(curPlayer, tick)
    
    #Çå¿ÕËùÓв»ÊôÓÚ×Ô¼ºµÄ¹â»·
    #__ClearNoMeAuraBuff(curPlayer)
    
    #Çå¿ÕËùÓÐÀ뿪µØÍ¼²»ÐèÒª±£´æµÄBuff
    __ClearLeaveNoSaveBuff(curPlayer)
    
    #---±£´æÍæ¼ÒÔÚÏßʱ¼ä(°´ÃëËã)---
    UpdateOnLineTime(curPlayer, tick)
    
    PassiveBuffEffMng.OnPlayerLeaveMap(curPlayer)
    
    #À뿪µØÍ¼Çå¿Õ¶ñÒâ¹¥»÷×Ô¼ºÍæ¼ÒÐÅÏ¢
    if curPlayer.GetPlayerID() in PyGameData.g_maliciousAttackDict:
        PyGameData.g_maliciousAttackDict.pop(curPlayer.GetPlayerID())
        
    PyGameData.g_needRefreshMapServerState = True # ÓÐÍæ¼ÒÀ뿪µØÍ¼ÉèÖÃÐèҪˢÐÂ
    
    PlayerSuccess.FinishDelayAddSuccessProgress(curPlayer, tick)
    playerID = curPlayer.GetPlayerID()
    if not isDisconnect:
        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)
    NPCCommon.ClearPriWoodPile(curPlayer)
    #ÒÆ³ýµØÍ¼»º´æµÄ¾³½çÄѶÈÍæ¼ÒIDÐÅÏ¢
    for playerIDList in PyGameData.g_realmDiffPlayerDict.values():
        if playerID in playerIDList:
            playerIDList.remove(playerID)
    return
##¸üб£´æÍæ¼ÒÔÚÏßʱ¼ä
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ätick
# @return 
def UpdateOnLineTime(curPlayer, tick):
    #---±£´æÍæ¼ÒÔÚÏßʱ¼ä(°´ÃëËã)---
    lastCalcTick = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcOLTimeTick)
    if lastCalcTick <= 0:
        curPlayer.SetDict(ChConfig.Def_PlayerKey_CalcOLTimeTick, tick)
        return
    
    curPlayer.SetDict(ChConfig.Def_PlayerKey_CalcOLTimeTick, tick)
    
    diffSec = (tick - lastCalcTick) / 1000
    if diffSec > 0:
        curPlayer.SetWeekOnlineTime(curPlayer.GetWeekOnlineTime() + diffSec)
        curPlayer.SetOnlineTime(curPlayer.GetOnlineTime() + diffSec)
        SyncOnLineTimeTotal(curPlayer)
        
    return
##ͬ²½ÔÚÏßʱ¼ä
# @param curPlayer Íæ¼ÒʵÀý
# @return 
def SyncOnLineTimeTotal(curPlayer):
    sendPack = ChPyNetSendPack.tagMCOnLineTimeTotal()
    sendPack.Clear()
    sendPack.OnLineTimeTotal = curPlayer.GetOnlineTime()
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
##ͬ²½×îºóÒ»´Î±³°ü¿ª¸ñÔÚÏßʱ¼ä
# @param curPlayer Íæ¼ÒʵÀý
# @param packType ±³°üÀàÐÍ
# @return 
def SyncOnLineTimeLastOpenPack(curPlayer, packType):
    return
    sendPack = ChPyNetSendPack.tagMCOnlineTimeLastOpenPack()
    sendPack.Clear()
    sendPack.PackType = packType
    sendPack.LastOnLineTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_LastAutoOpenPackTick % packType)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
##À뿪µØÍ¼Çå¿Õ²»±£´æµÄBuff
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks À뿪µØÍ¼Çå¿Õ²»±£´æµÄBuff
def __ClearLeaveNoSaveBuff(curPlayer):
    #×°±¸BuffºÍ±»¶¯BuffÕâÀï²»Çå, Çл»µØÍ¼ºó»áÖØÐ¼ÆËã
    
    #Çå¿ÕËùÓг¡¾°ÀàBuff
    curPlayer.GetMapBuff().Clear()
    
    #2011-01-28 ÐÞ¸ÄΪ¿É±£´æ£¬¹Ê´Ë´¦²»É¾³ý
    #Çå¿ÕËùÓпØÖÆÀàBUFF
    #BUG: ¿ØÖÆÀàBUFF²»´æÊý¾Ý¿â£¬ÇеØÍ¼ºó²»Í¨ÖªÏûʧ£¬¿Í»§¶ËÎÞ·¨É¾³ý
    #curPlayer.GetActionBuffManager().Clear()
    return
## Çå³ýÏÂÏßÏûʧµÄbuff, ÔÚ¸üÐÂÅÅÐаñ֮ǰ
#  @param curPlayer: Íæ¼ÒʵÀý
#  @return 
def __DisconnectClearBuff(curPlayer, tick):
    #ÐèÒª¿¼ÂÇbuff,deBuff,aura,incBuff,mapBuff,³ýÁËequipBuff²»¿¼ÂÇ
    PlayerClearBuff_Single(curPlayer, curPlayer.GetBuffState(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetDeBuffState(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetAura(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetIncBuff(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetMapBuff(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetActionBuffManager(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetProcessBuffState(), ClearBuffByDisconnect, tick)
    PlayerClearBuff_Single(curPlayer, curPlayer.GetProcessDeBuffState(), ClearBuffByDisconnect, tick)
    
    #BUFFЧ¹ûÔÚÍâ²ã¼ÆËã
    #SkillShell.RefreshPlayerBuffOnAttrAddEffect(curPlayer)
    return
#---------------------------------------------------------------------
##Íæ¼ÒÀ뿪·þÎñÆ÷
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÀ뿪·þÎñÆ÷
def PlayerLeaveServer(curPlayer, tick):
    #³èÎïÏÂÏßÂß¼, ÕâÀïÒª½øÐÐÅÅÐаñ, ÓÅÏÈ×ö, ±ÜÃâÍæ¼Ò¹â»·µÈÊôÐÔÓ°Ïì³èÎïÊôÐÔʧЧ
    #PetControl.DoLogic_PetInfo_OnLeaveServer(curPlayer, tick)
    
    #Çå³ýÏÂÏßÏûʧµÄbuff, ÔÚ¸üÐÂÅÅÐаñ֮ǰ
    __DisconnectClearBuff(curPlayer, tick)
    
    #Çå³ý»ØÊÕÕ½
    #DelRecylcePack(curPlayer)
    
    #ÖØÐÂˢнÇÉ«ÊôÐÔ
    playerControl = PlayerControl(curPlayer)
    playerControl.RefreshAllState()
            
    #Íæ¼ÒÏÂÏ߸üÐÂÅÅÐаñ
    PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer) #ÅÅÐаñÒÑʵʱ¸üУ¬¹ÊÏÂÏß²»ÔÙͬ²½
    
    #Íæ¼ÒÏÂÏß֪ͨgameserver¼Ç¼»º´æ£¨·ÅÔÚÏÂÏ߸üÐÂÅÅÐаñÖ®ºó£¬·½±ãGameserverÅжÏÊÇ·ñÐèÒª´æÈëÊý¾Ý¿âÖУ©
    PlayerViewCacheTube.OnPlayerLogOut(curPlayer, tick)
    
    #Íæ¼ÒÏÂÏß/Íæ¼ÒÇл»µØÍ¼¹«ÓÃÂß¼
    __PlayerLeaveServerLogic(curPlayer, tick, True)
    #ÆïÂíÍæ¼ÒÏÂÏßÂß¼
    __RidingHorsePlayerDisconnect(curPlayer)
    #ïÚ³µÏÂÏßÂß¼
    __TruckPlayerDisconnect(curPlayer)
    #ÕÙ»½ÊÞËÀÍö
    KillPlayerSummonNPC(curPlayer)
    #¸üдӱ¾µØÍ¼ÀëÏßÐÅÏ¢
    PyGameData.g_disconnectPlayer[curPlayer.GetPlayerID()] = [tick, curPlayer.GetPosX(), curPlayer.GetPosY()]
    GameWorld.DebugLog("Íæ¼Ò´Ó±¾µØÍ¼ÀëÏß: %s" % PyGameData.g_disconnectPlayer, curPlayer.GetPlayerID())
    return
def GetPlayerLeaveServerTick(playerID):
    # »ñÈ¡Íæ¼Ò´Ó±¾µØÍ¼ÖÐÀëÏßʱµÄtick, ×î´óÖ§³Ö1Сʱ, Èç¹ûÓÐÐèÒª´óÓÚ1СʱµÄÇëµ÷Õû³¬Ê±ÏÞÖÆ
    # ×¢: ·µ»ØÖµÎª0ʱ£¬Ö»ÄÜ´ú±íÍæ¼Ò²»ÊÇÔÚ±¾µØÍ¼ÀëÏß1СʱÄÚ£¬²¢²»ÄÜ´ú±íÍæ¼Òµ±Ç°ÊÇ·ñÔÚÏß״̬£¬¿ÉÄÜÔÚÆäËûµØÍ¼
    if playerID not in PyGameData.g_disconnectPlayer:
        return 0
    return PyGameData.g_disconnectPlayer[playerID][0]
def GetPlayerLeaveServerPos(playerID):
    # »ñÈ¡Íæ¼Ò´Ó±¾µØÍ¼ÖÐÀëÏßʱµÄ×ø±ê
    # ×¢£ºÊ¹Óñ¾º¯Êýʱ£¬Ò»¶¨ÒªÏÈʹÓú¯Êý GetPlayerLeaveServerTick È·±£ÊÇ´Ó±¾µØÍ¼ÖÐÀëÏߵIJſÉʹÓÃ
    # @return: posX, posY
    if playerID not in PyGameData.g_disconnectPlayer:
        return 0, 0
    return PyGameData.g_disconnectPlayer[playerID][1:3]
def RemoveTimeoutLeaveServerPlayerInfo(tick):
    # Ôݶ¨Ã¿ÌìÁ賿5µãÖ´ÐÐÒ»´Î
    for playerID, leaveInfo in PyGameData.g_disconnectPlayer.items():
        leaveTick = leaveInfo[0]
        if tick - leaveTick > 3600000: # Çå³ý³¬Ê±1СʱµÄ¼Ç¼
            PyGameData.g_disconnectPlayer.pop(playerID)
    return
def RemoveLeaveServerPlayerInfo(playerID):
    # ÉÏÏßÒÆ³ýÔÚ±¾µØÍ¼ÏÂÏߵļǼ
    if playerID in PyGameData.g_disconnectPlayer:
        PyGameData.g_disconnectPlayer.pop(playerID)
        GameWorld.DebugLog("½øÈë±¾µØÍ¼£¬ÒƳýÉÏ´ÎÔÚ±¾µØÍ¼ÀëÏ߼Ǽ!", playerID)
    return
##Çå³ý»ØÊÕÕ½
# @param None
# @return None
def DelRecylcePack(curPlayer):
    backPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptRecycle)
    
    for i in range(backPack.GetCount()):
        curItem = backPack.GetAt(i)
        
        if not curItem or curItem.IsEmpty():
            continue
        
        curItem.Clear()
    
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_DelPackIndex, 0)
    return
##Çл»µØÍ¼ïÚ³µÉ趨
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÕæ,¿ÉÒÔ´øÉÏïÚ³µÇл»µØÍ¼
# @remarks Çл»µØÍ¼ïÚ³µÉ趨
def __GetCanChangeMapSetTruck(curPlayer):
    curTruck = curPlayer.GetTruck()
    #GameWorld.Log("Íæ¼Ò æô³µ Çл»µØÍ¼Âß¼")
    if curTruck == None:
        #GameWorld.Log("Íæ¼Ò ûÓÐ æô³µ")
        return False
    
    dist = GameWorld.GetDist(curTruck.GetPosX(), curTruck.GetPosY(),
                             curPlayer.GetPosX(), curPlayer.GetPosY())
    if dist > ChConfig.Def_PlayerTruckEventDist:
        #GameWorld.Log("Íæ¼ÒºÍæô³µ¾àÀë¹ýÔ¶, æô³µ²»Çл»  %d" %dist)
        return False
    
#    #Íæ¼ÒÏÂæô³µ
#    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvTruck :
#        PlayerTruck.PlayerTruckDown(curPlayer,curTruck)
    #GameWorld.Log("Íæ¼ÒºÍæô³µÒ»ÆðÇл»µØÍ¼")
    #1. ÔÚ¶Ô·½µØÍ¼´´½¨æô³µ
    #curTruck.ResetWorldPos(mapID, targetPosX, targetPosY)
    #2. Ïûʧ±¾µØÍ¼æô³µ
    
    return True
#---------------------------------------------------------------------
##Íæ¼Ò¿ªÊ¼Çл»µØÍ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò¿ªÊ¼Çл»µØÍ¼
def DoPlayerResetWorldPos(curPlayer, tick):
    NotifyStartChangeMap(curPlayer) # ֪ͨ¿ªÊ¼Çл»µØÍ¼
    #Ôڴ˺¯ÊýÖв»¿ÉÖжÏ, Ò»¶¨Òªµ÷ÓÃDoResetWorldPosAndClearº¯Êý
    #·ñÔò, »áÔÚBalanceServerÖп¨×¡
    takeTruck = curPlayer.GetChangeMapTakeTruck()
    
    #Èç¹ûÓÐæô³µ, ´øÉÏæô³µ
    if takeTruck == True:
        if not __GetCanChangeMapSetTruck(curPlayer):
            takeTruck = False
            
    #Èç¹û²»Èôøæô³µ, ²¢ÇÒÍæ¼ÒÔÚÈËïÚºÏһ״̬, ÄÇôÈÃÍæ¼Òϳµ
    if takeTruck == False and curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvTruck:
        curTruck = curPlayer.GetTruck()
        if curTruck:
            PlayerTruck.PlayerTruckDown(curPlayer, curTruck)
        
    curPlayer.SetChangeMapTakeTruck(takeTruck)
    
    #À뿪µØÍ¼·þÎñÆ÷
    __PlayerLeaveServerLogic(curPlayer, tick, False)
    
    FBLogic.DoPlayerChangeMapLogic(curPlayer, tick)
    #summonList = list()
    #ÕٻسèÎï
    PetControl.ReCallFightPet(curPlayer)
    #1. ɾ³ý×Ô¼º²»ÐèÒªµÄÕÙ»½ÊÞ(»ðÑæÖ®ÁéµÈ)
    #±ØÐëÓÃwhile, ÒòΪÔÚÑ»·ÖÐҪɾ³ý
    # ÕÙ»½ÊÞÇеØÍ¼²»´ø¹ýÈ¥
    while curPlayer.GetSummonCount():
        summonNPC = curPlayer.GetSummonNPCAt(0)
        NPCCommon.SetDeadEx(summonNPC)
#    summonIndex = 0
#    while summonIndex < curPlayer.GetSummonCount():
#        summonNPC = curPlayer.GetSummonNPCAt(summonIndex)
#        
#        #2009.4.21, Èç¹ûÕÙ»½ÊÞµÄËÙ¶ÈΪ0, ´ú±íÕâ¸öÕÙ»½ÊÞΪÕÈ×Ó
#        #Çл»µØÍ¼²»¿É´ø¹ýÈ¥
#        #֮ǰÓÃÓ²Åж¨µÄ
#        if summonNPC.GetSpeed() == 0:
#            #Çл»µØÍ¼²»ÄÜ´ø¹ýÈ¥
#            NPCCommon.SetDeadEx(summonNPC)
#            continue
#            
#        #Çл»µØÍ¼¿ÉÒÔ´ø¹ýÈ¥ , Çå¿ÕÕÙ»½ÊÞ³ðºÞ,ÉËѪÁбí
#        summonNPCControl = NPCCommon.NPCControl(summonNPC)
#        summonNPCControl.ClearNPCAngry()
#        summonNPCControl.ClearNPCHurtList()
#        summonList.append(summonNPC)
#        summonIndex += 1
        
    changeMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeMapID)
    # ¸üÐÂ×îºóÒ»´ÎÀ뿪µÄ·ÇÖÐÁ¢³£¹æµØÍ¼, ´ÓÖÐÁ¢µØÍ¼Í˳öʱÐèÒª»Øµ½¸ÃµØ·½£¬±ØÐëÔÚ 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() # ³£¹æµØÍ¼Ó÷ÖÏßID
        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))
    # µ±Ç°Êǿɷµ»ØµÄ¸±±¾µØÍ¼ ÇÒ Ä¿±êµØÍ¼Îª¸±±¾
    elif curPlayer.GetMapID() in ChConfig.Def_CanBackFBMap and curPlayer.GetMapID() != changeMapID \
        and GameWorld.GetMap().GetMapFBTypeByMapID(changeMapID) != IPY_GameWorld.fbtNull:
        mapID = curPlayer.GetMapID()
        posX = curPlayer.GetPosX()
        posY = curPlayer.GetPosY()
        lineID = GetFBFuncLineID(curPlayer) # ¸±±¾Óù¦ÄÜÏß·ID
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBMapID, mapID)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBPosX, posX)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBPosY, posY)
        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:
        #ĬÈÏ»ØÂúѪ
        if GameObj.GetHP(curPlayer) > 0 and curPlayer.GetPlayerAction() != IPY_GameWorld.paDie and GameObj.GetHP(curPlayer) < GameObj.GetMaxHP(curPlayer):
            GameObj.SetHPFull(curPlayer)
            
    #2. µ÷ÓÃÇл»µØÍ¼½Ó¿Ú
    curPlayer.DoResetWorldPosAndClear()
    
    #3. Íæ¼ÒÒѾ´«Ë͹ýÈ¥ÁË, ɾ³ýÕâ¸öÍæ¼ÒµÄ¸½¼ÓÕÙ»½ÊÞ(æô³µ, »òÕß»ÆÈªÊ¹Õß)
    #for curSummon in summonList:
    #    NPCCommon.SetDeadEx(curSummon)
        
    if takeTruck == True:
        curTruck = curPlayer.GetTruck()
        
        if curTruck != None:
            curPlayer.SetTruck(None)
            curTruck.Disappear()
            
    return
#---------------------------------------------------------------------
##Íæ¼ÒÀ뿪¸±±¾
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÀ뿪¸±±¾
def PlayerLeaveFB(curPlayer):
    if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RouteServerInitOK):
        #RouteServerδ³õʼ»¯²»ÔÊÐíÇл»µØÍ¼, »º´æ´¦Àí
        GameServerRefresh.Set_PlayerRouteServerInitOK_OnLeaveFB(curPlayer, 1)
        return
    
    GameWorld.Log("PlayerLeaveFB...", curPlayer.GetPlayerID())
    if GameWorld.IsCrossServer():
        CrossRealmPlayer.PlayerExitCrossServer(curPlayer)
        return
    
    funcLineID = 0
    enterFBFree = False
    #ÖÐÁ¢µØÍ¼»Øµ½ÉÏÒ»´Î·ÇÖÐÁ¢³£¹æµØÍ¼    
    if curPlayer.GetMapID() in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4) or curPlayer.GetMapID() in ChConfig.Def_CanBackFBMap:
        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)
        # ÖØÖÃ
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromMapID, 0)
        # ÀϺÅÖ§³Ö£¬±¾À´¾ÍÔÚÖÐÁ¢µØÍ¼µÄ£¬·µ»ØÐÂÊÖ´å
        if not mapID:
            ipyData = IpyGameDataPY.GetIpyGameData("CreateRole", curPlayer.GetRoleType())
            if not ipyData:
                return
            mapID, posX, posY = ipyData.GetCreateRoleMap()
            lineID = 0
            
    #À뿪¸±±¾
    else:
        fromFBMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromFBMapID)
        # »Øµ½ÉÏÒ»´Î¿É·µ»ØµÄ¸±±¾Àï
        if fromFBMapID:
            mapID = fromFBMapID
            posX = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromFBPosX)
            posY = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromFBPosY)
            lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromFBLineID)
            funcLineID = lineID # »Ø¸±±¾µÄÒªÖ¸¶¨¹¦ÄÜÏß·ID
            enterFBFree = True # ·µ»ØµÄÃâ·Ñ½øÈë
            # ÖØÖÃ
            NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBMapID, 0)
            GameWorld.DebugLog("À뿪¸±±¾£¬·µ»Ø¿É֮ǰ¿É·µ»ØµÄ¸±±¾! fromFBMapID=%s,lineID=%s,posXY(%s,%s)" % (mapID, lineID, posX, posY))
        else:
            mapID = curPlayer.GetFromMapID()
            posX = curPlayer.GetFromPosX()
            posY = curPlayer.GetFromPosY()
            lineID = curPlayer.GetFromLineID()
            
    if mapID == curPlayer.GetMapID():
        # Èç¹ûÔÚͬһÕŵØÍ¼, È¡DBÖØÉúµã, ÆÕͨµØÍ¼ÏÂÏßÖØÉÏʱFromMapID»á±»ÉèÖÃΪ±¾µØÍ¼
        gameMap = GameWorld.GetMap()
        mapID, posX, posY = gameMap.GetRebornMapID(), gameMap.GetRebornMapX(), gameMap.GetRebornMapY()
        #posX, posY = GameMap.GetNearbyPosByDis(posX, posY, ChConfig.Def_RebornPos_Area_Range)
        
    #copyMapID = curPlayer.GetCopyMapID()
    GameWorld.Log("PlayerLeaveFB MapID = %d, PosX = %d, PosY = %d" % (mapID, posX, posY), curPlayer.GetPlayerID())
    
    if GameWorldProcess.IsNoPlayerNeedCloseFB() and GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount() == 1:
        #Èç¹û¸±±¾ÖÐÖ»ÓÐÕâÒ»¸öÈË, ÄÇô°ÑÕâ¸ö¸±±¾ÉèÖÃÎªÍæ¼Ò°²È«ÏÂÏß, ¹Ø±Õ¸±±¾
        gameFB = GameWorld.GetGameFB()
        gameFB.SetIsSafeClose(1)
    
    #===============================================================================================
    # #Èç¹ûÍæ¼ÒÊÇËÀÍö״̬£¬ÔòÏȸ´»î£¬ÊÖÓβ߻®²»Ï븴»îÍ˳ö
    # if curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
    #    curPlayer.Reborn(ChConfig.rebornType_System)
    #    GameObj.SetHPFull(curPlayer)
    #    ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
    #===============================================================================================
    
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, lineID, funcLineID=funcLineID, enterFBFree=enterFBFree)
    
    #ÔÚ¿ÕÏлòÕßÒÆ¶¯×´Ì¬ÏÂ,²ÅÄÜËøËÀÍæ¼Ò
    if curPlayer.GetPlayerAction() in [IPY_GameWorld.paNull] or curPlayer.IsMoving():
        #°ÑÍæ¼ÒËøËÀ
        curPlayer.BeginEvent()
    
    return
#---------------------------------------------------------------------
def PlayerEnterCrossServer(curPlayer, mapID, lineID):
    playerID = curPlayer.GetPlayerID()
    GameWorld.Log("Íæ¼ÒÇëÇó½øÈë¿ç·þµØÍ¼: mapID=%s,lineID=%s" % (mapID, lineID), playerID)
    if mapID not in ChConfig.Def_CrossMapIDList:
        return
    
    tick = GameWorld.GetGameWorld().GetTick()
    lastRequestTick = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RequestEnterCrossServerTick)
    if lastRequestTick and tick - lastRequestTick < 5000:
        GameWorld.DebugLog("    ÇëÇó½øÈë¿ç·þCDÖÐ!", playerID)
        NotifyCode(curPlayer, "RequestEnterCrossServerCD")
        return
    
    crossRegisterMap = curPlayer.NomalDictGetProperty(ChConfig.Def_PlayerKey_CrossRegisterMap)
    if crossRegisterMap:
        GameWorld.ErrLog("¿ç·þÒѾÔÚÉÏ´«Êý¾Ý£¬²»Öظ´Ìá½»!crossRegisterMap=%s,mapID=%s" % (crossRegisterMap, mapID), playerID)
        return
    
    if GameWorld.IsCrossServer():
        GameWorld.DebugLog("¿ç·þ·þÎñÆ÷²»ÔÊÐí¸Ã²Ù×÷!")
        return
    
    if GetCrossMapID(curPlayer):
        GameWorld.ErrLog("Íæ¼Òµ±Ç°Îª¿ç·þ״̬£¬²»ÔÊÐíÔÙ´ÎÇëÇó½øÈë¿ç·þ!", curPlayer.GetPlayerID())
        return
    
    if not CrossRealmPlayer.IsCrossServerOpen():
        NotifyCode(curPlayer, "CrossMatching18")
        return
    
    if GameObj.GetHP(curPlayer) <= 0:
        NotifyCode(curPlayer, "CrossMap4")
        return
    
    if PlayerCrossRealmPK.GetIsCrossPKMatching(curPlayer):
        NotifyCode(curPlayer, "CrossMap3")
        return
    
    if PlayerState.IsInPKState(curPlayer):
        NotifyCode(curPlayer, "SingleEnterPK", [mapID])
        return
    
    fbIpyData = FBCommon.GetFBIpyData(mapID)
    if fbIpyData:
        fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID, False)
        if not fbLineIpyData:
            GameWorld.DebugLog("¸±±¾±íÕÒ²»µ½¸±±¾¶ÔÓ¦¹¦ÄÜÏß·!mapID=%s,lineID=%s" % (mapID, lineID))
            return
        ret = FBCommon.CheckCanEnterFBComm(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData)
        if ret != ShareDefine.EntFBAskRet_OK:
            return
        
        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")
            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)
        GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_EnterFB, msgDict)
    else:
        isSend = GY_Query_CrossRealmReg.RegisterEnterCrossServer(curPlayer, mapID, lineID=lineID)
        if not isSend:
            return
    curPlayer.SetDict(ChConfig.Def_PlayerKey_RequestEnterCrossServerTick, tick)
    return
##Íæ¼Ò½øÈ븱±¾
# @param curPlayer Íæ¼ÒʵÀý
# @param mapID µØÍ¼ID
# @param posX ×ø±êX
# @param posY ×ø±êY
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Òµ¥¶À½øÈ븱±¾
def PlayerEnterFB(curPlayer, mapID, lineID, posX=0, posY=0):
    mapID = FBCommon.GetRecordMapID(mapID)
    GameWorld.Log("Íæ¼ÒÇëÇó½øÈ븱±¾! mapID=%s,lineID=%s,posX=%s,posY=%s" 
                  % (mapID, lineID, posX, posY), curPlayer.GetPlayerID())
    
    # µ±ÈÕ»»Õ½Ã˲»¿É½øÈëµÄµØÍ¼, ¸ÄΪ°´Ð¡Ê±Ëã
    #if mapID in ChConfig.Def_ChangeFamilyCanNotEnterMap:
    #    if PlayerFamily.GetPlayerChangeFamilyPastHour(curPlayer) < 24:
    #        NotifyCode(curPlayer, 'jiazu_xyj_671654')
    #        return
        
#    #¿ç·þ»î¶¯ÈËÊý·ÖÁ÷´¦Àí
#    if GameWorld.IsCrossServer():
#        reqMapID = mapID
#        mapID = __GetMergeFBPlayerMapID(curPlayer, reqMapID)
#        if not mapID:
#            GameWorld.ErrLog("ÕÒ²»µ½¿É·ÖÅä½øÈëµÄ¿ç·þ»î¶¯µØÍ¼ID! reqMapID=%s" % reqMapID)
#            return
      
    #¹ýÂË·â°üµØÍ¼ID
    if not GameWorld.GetMap().IsMapIDExist(mapID):
        GameWorld.ErrLog('###·Ç·¨µØÍ¼Êý¾Ý£¬mapID: %s' % (mapID), curPlayer.GetID())
        return
 
#    if not GameWorld.GetMap().CanMove(curPlayer.GetPosX(), curPlayer.GetPosY()):
#        # ×ø±ê²»¿ÉÒÆ¶¯Ôò²»ÄÜ´«ËÍ£¬²»È»»áµ¼ÖÂÍ˳ö¸±±¾ÎÞ·¨ÍË»ØÀ´Ô´µØ
#        GameWorld.ErrLog("ÔÕϰµãÎÞ·¨Çл»µØÍ¼ %s" % ([curPlayer.GetPosX(), curPlayer.GetPosY()]))
#        return
 
    #½øÈ븱±¾Í¨Óüì²é
    fbIpyData = FBCommon.GetFBIpyData(mapID)
    fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID)
    sceneMapID = mapID if not fbLineIpyData else fbLineIpyData.GetMapID()
    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)
        
        if not retPos:
            GameWorld.ErrLog("δÕÒµ½½øÈ븱±¾×ø±ê£¡mapID=%s,lineID=%s" % (mapID, lineID))
            return
        
        posX, posY = retPos
        
    #===============================================================================================
    # if not EventShell.DoLogic_EnterFbGameEvent(curPlayer, mapID, tick):
    #    GameWorld.Log("DoLogic_EnterFbGameEvent False£¡mapID=%s,lineID=%s" % (mapID, lineID))
    #    return 
    #===============================================================================================
    
    if curPlayer.IsMoving():
        curPlayer.StopMove()
    
    fbID = 0 # ºó¶ËµÄÐéÄâÏß·
    isSendToGameServer = False
    mapFBType = GameWorld.GetMap().GetMapFBTypeByMapID(sceneMapID) # ÅжÏÊÇ·ñ×é¶Ó±¾ÐèÒªÒÔ³¡¾°µØÍ¼Åжϣ¬ÒòΪ²ß»®¿ÉÄÜÉ趨²»Í¬¹¦ÄÜÏß·IDµÄ¸±±¾ÀàÐͲ»Ò»Ñù£¬±ÈÈçС¾³½ç¡¢´ó¾³½ç
    if mapFBType == IPY_GameWorld.fbtTeam and curPlayer.GetTeamID():
        if curPlayer.GetTeamLV() != IPY_GameWorld.tmlLeader:
            GameWorld.Log("·Ç¶Ó³¤£¬ÎÞ·¨·¢Æð½øÈë×é¶Ó¸±±¾ÇëÇó!", curPlayer.GetPlayerID())
            return
        isSendToGameServer = True
    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("·âħ̳ÐéÄâÏß·ֻÄÜͨ¹ý×Ô¶¨Ò峡¾°½øÈëÌôÕ½£¡")
                #PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, fbID, funcLineID=lineID)
                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)
            extendParamList = [enterCnt]
        SendToGameServerEnterFB(curPlayer, mapID, lineID, tick, extendParamList)
        return
    
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, fbID, funcLineID=lineID)
    return
##·¢Ë͵½GameServerÇëÇó½øÈ븱±¾
#@param curPlayer Íæ¼Ò
#@param mapID µØÍ¼id
#@param lineID Ïß·id
#@param tick ʱ¼ä´Á
#@return ·µ»ØÖµÎÞÒâÒå
def SendToGameServerEnterFB(curPlayer, mapID, lineID, tick, extendParamList=[]):
    #lineID = FBLogic.GetPlayerFBLineID(curPlayer, mapID, tick)
    
    GameWorld.Log("SendToGameServerEnterFB mapID=%s,lineID=%s,extendParamList=%s" 
                  % (mapID, lineID, extendParamList), curPlayer.GetID())
    # »ñÈ¡Íæ¼ÒËùÊô·ÖÏß
    if lineID == None:
        lineID = FBLogic.GetPlayerFBLineID(curPlayer, mapID, tick)
        
    #GameWorld.DebugLog("send GameServer_QueryPlayerByID")
    # ÇëÇóGameServerÄ¿±ê¸±±¾GameWorldË÷Òý
    sendMsg = [mapID, lineID]
    sendMsg.extend(extendParamList)
    sendMsg = "%s" % sendMsg
    curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_EnterFB, 0, 'EnterFB', sendMsg, len(sendMsg))
    return
    
##¼ì²éÍæ¼Ò״̬ÊÇ·ñ¿ÉÒÔÒÆ¶¯µ½¸±±¾
#@param curPlayer Íæ¼ÒʵÀý
#@return ·µ»ØÖµÎÞÒâÒå
#@remarks ¼ì²éÍæ¼Ò״̬ÊÇ·ñ¿ÉÒÔÒÆ¶¯µ½¸±±¾
def CheckMoveToFB(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, tick, isNotify=True, isTeamAsk=False):
    '''ÅжϿɷñ½øÈ븱±¾£¬°üº¬ÊÖ¶¯¼°Æ¥Åä
    @param isTeamAsk: ÊÇ·ñÊǶÓÎé½øÈëÇëÇóµÄ£¬Ò»°ãÊǶÓÎé״̬Ï£¬¶Ó³¤·¢Æð½øÈ븱±¾£¬ÐèÒª¼ì²é¶ÓÔ±¿É·ñ½øÈ룬´ËʱΪTrue£¬¿É×öһЩ¸½¼Ó´¦Àí
    @note: ²ß»®ÒªÇóÌáʾ°´ÓÅÏȼ¶À´£¬¸±±¾×ÔÉíµÄÌõ¼þÏÞÖÆÓÅÏÈÌáʾ£¬ÆäËû¸½¼ÓÌáʾÓÅÏȼ¶½ÏµÍ
    '''
    ret = FBCommon.CheckCanEnterFBComm(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, 1, isNotify, isTeamAsk)
    if ret != ShareDefine.EntFBAskRet_OK:
        return ret
    
    if GameObj.GetHP(curPlayer) <= 0:
        GameWorld.Log("Íæ¼ÒÒѾËÀÍö, ÎÞ·¨½øÈ븱±¾!")
        return ShareDefine.EntFBAskRet_Dead
    
    if PlayerTJG.GetIsTJG(curPlayer):
        if isNotify:
            NotifyCode(curPlayer, "SingleEnterDefaul", [mapID])
        return ShareDefine.EntFBAskRet_TJG
    
    ## ¶ÓÎé¼ì²éµÄÇé¿ö£¬¶Ó³¤²»´¦Àí£¬Ö»´¦Àí¶ÓÔ±
    if isTeamAsk and curPlayer.GetTeamLV() != IPY_GameWorld.tmlLeader:
        # ºó¶ËÖ»×öboss״̬Ï£¬±»¶¯½øÈ븱±¾ÏÞÖÆ£¬·ÀÖ¹´òbossÖб»À½øÈ¥¸±±¾
        # boss״̬µÄÆäËû´«ËÍÏÞÖÆÓÉǰ¶Ë¿ØÖÆ£¬ÒòΪ²ß»®Òª¸ù¾Ý½çÃæÀ´´¦Àí£¬ÓÐЩ½çÃæÔÊÐí´«ËÍ£¬ÓÐЩ²»ÔÊÐí
        if PlayerState.IsInBossState(curPlayer):
            return ShareDefine.EntFBAskRet_BossState
        
    ## PK״̬¼ì²é
    if PlayerState.IsInPKState(curPlayer):
        if isNotify:
            NotifyCode(curPlayer, "SingleEnterPK", [mapID])
        return ShareDefine.EntFBAskRet_PKState
    
    ## ¿ç·þPKÆ¥ÅäÖÐ
    if PlayerCrossRealmPK.GetIsCrossPKMatching(curPlayer):
        if isNotify:
            NotifyCode(curPlayer, "CrossMatching8", [mapID])            
        return ShareDefine.EntFBAskRet_CrossPKMatching
    
    ## ¿ç·þµØÍ¼ÖÐ
    if GetCrossMapID(curPlayer) and mapID not in ChConfig.Def_CrossMapIDList:
        if isNotify:
            NotifyCode(curPlayer, "CrossMap5", [mapID])
        return ShareDefine.EntFBAskRet_InCrossMap
    
    #===============================================================================================
    # # ÕâÀï²»×ö״̬ÏÞÖÆ£¬ÓÉǰ¶Ë´¦Àí£¬ÒòΪ²ß»®Òª¸ù¾Ý½çÃæÀ´´¦Àí£¬Í¬Ò»´«Ë͹¦ÄÜÓпÉÄÜÔÚ²»Í¬½çÃæ
    # # PK״̬¼ì²é
    # if PlayerState.IsInPKState(curPlayer):
    #    if isNotify:
    #        NotifyCode(curPlayer, "SingleEnterPK", [mapID])
    #    return ShareDefine.EntFBAskRet_PKState
    # 
    # # ´òboss״̬¼ì²é
    # if PlayerState.IsInBossState(curPlayer):
    #    if isNotify:
    #        NotifyCode(curPlayer, "SingleEnterBoss", [mapID])
    #    return ShareDefine.EntFBAskRet_BossState
    #===============================================================================================
    
    playerAction = curPlayer.GetPlayerAction()
    if playerAction == IPY_GameWorld.paPreparing:
        if isNotify:
            NotifyCode(curPlayer, "SingleEnterGather", [mapID])
        return ShareDefine.EntFBAskRet_Preparing
    
    if playerAction == IPY_GameWorld.paSit:
        if isNotify:
            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:
            NotifyCode(curPlayer, "Carry_lhs_697674")
        return ShareDefine.EntFBAskRet_Other
    
    for index in ChConfig.Def_Player_NotCan_EnterFbPyGameEvenState:
        if GetPyPlayerAction(curPlayer, index):
            #Carry_lhs_697674£ºÄúµ±Ç°Ëù´¦µÄ״̬²»ÄܽøÐд«ËÍ!
            if isNotify:
                NotifyCode(curPlayer, "Carry_lhs_697674")
            return ShareDefine.EntFBAskRet_Other
        
    #ÒÆ¶¯Öв»Ö´Ðд˲Ù×÷
#    if curPlayer.IsMoving():
#        #NotifyCode(curPlayer, "GeRen_lhs_0")
#        return False
#    #ÀïÚÖÐÎÞ·¨´«Ë͵½¸±±¾
#    if curPlayer.GetTruck():
#        #NotifyCode(curPlayer, "Convey_Duplicate_Lost01")
#        return False
    #Õ½¶·×´Ì¬ÖÐÎÞ·¨´«Ë͵½¸±±¾
    #if curPlayer.IsBattleState():
    #    NotifyCode(curPlayer, "Carry_lhs_202580")
    #    return False
    #µ±Ç°µØÍ¼²»ÊÇÆÕͨµØÍ¼
    if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
        canFBMoveToOther = False
        fbEnableTransportMap = ReadChConfig.GetEvalChConfig("FBEnableTransportMap")
        curMapID = GameWorld.GetMap().GetMapID()
        if curMapID in fbEnableTransportMap and mapID in fbEnableTransportMap[curMapID]:
            canFBMoveToOther = True
        if curMapID in ChConfig.Def_CanBackFBMap:
            canFBMoveToOther = True
        toMapFBType = GameWorld.GetMap().GetMapFBTypeByMapID(mapID)
        if toMapFBType == IPY_GameWorld.fbtNull:
            if curMapID in IpyGameDataPY.GetFuncEvalCfg('DungeonDeliver', 1):
                canFBMoveToOther = True
        elif FBCommon.GetRecordMapID(curMapID) == FBCommon.GetRecordMapID(mapID):
            if FBLogic.CanChangeSameDataMapFB(curPlayer, mapID, lineID):
                canFBMoveToOther = True
                
        if not canFBMoveToOther:
            if isNotify:
                NotifyCode(curPlayer, "SingleEnterDungeon", [mapID])
            return ShareDefine.EntFBAskRet_InFB
    
    if not FBLogic.OnEnterFBEvent(curPlayer, mapID, lineID, tick):
        GameWorld.DebugLog("    OnEnterFBEvent False!", curPlayer.GetPlayerID())
        if isNotify:
            NotifyCode(curPlayer, "SingleEnterDefaul")
        return ShareDefine.EntFBAskRet_Other
    
    return ShareDefine.EntFBAskRet_OK
#---------------------------------------------------------------------
##Ë¢ÐÂÍæ¼ÒʱÖÓ£¬ÇеØÍ¼Íæ¼ÒʱÖӼǼÇå¿Õ£¬´¦ÀíÏàÓ¦Âß¼
# @param curPlayer Íæ¼Ò
# @return ÎÞÒâÒå
# @remarks Ë¢ÐÂÍæ¼ÒʱÖÓ£¬ÇеØÍ¼Íæ¼ÒʱÖӼǼÇå¿Õ£¬´¦ÀíÏàÓ¦Âß¼
def RefreshPlayerTick(curPlayer):
    tick = GameWorld.GetGameWorld().GetTick()
    
    #·À³ÁÃÔÇÐÏßʱ¼ä
    PlayerGameWallow.DoLogic_WallowOnlineTime(curPlayer, tick)
    return
#---------------------------------------------------------------------
def PlayerResetWorldPosFBLineID(curPlayer, mapID, posX, posY, funcLineID):
    '''Íæ¼ÒÇл»µ½Ö¸¶¨¸±±¾¶ÔÓ¦µÄ¹¦ÄÜÏß·ID£¬ÊÊÓÃÓڶೡ¾°ºÏ²¢Ò»ÕŵØÍ¼µÄÇé¿ö£¬ºó¶ËÐèÔÚͬһÕÅÎïÀíµØÍ¼²ÅÄÜʹÓøú¯Êý
    ÓÉÓÚǰ¶ËµØÍ¼ºÏ²¢µÄ³¡¾°¼ÓÔØÊÇ·Ö¿ªµÄ£¬ËùÒÔÔÚÇг¡¾°µÄʱºò²»ÄÜÖ±½ÓÉèÖÃ×ø±ê£¬ÒòΪǰ¶Ëʵ¼ÊÉϲ»´æÔÚ¸Ã×ø±ê
    Íæ¼ÒÖ±½ÓÔÚµØÍ¼ÖÐÇл»¹¦ÄÜÏß·ID£¬´Ëʱǰ¶ËÐèÒª×ßÕý³£µÄÇÐͼÁ÷³Ì²ÅÄܼÓÔØÄ¿±ê¹¦ÄÜÏß·ID¶ÔÓ¦µÄ³¡¾°
    ¹ÊÕâÀï×ö¸öÐé¼ÙÇÐͼÁ÷³Ì
    '''
    if curPlayer.GetMapID() != mapID:
        return
    
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqFBFuncLine, funcLineID)
    GameWorld.Log("Íæ¼Ò¸±±¾Öбä¸ü¹¦ÄÜÏß·ÐéÄâÇеØÍ¼: mapID=%s,posX=%s,posY=%s,funcLineID=%s" 
                  % (mapID, posX, posY, funcLineID), curPlayer.GetPlayerID())
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ChangeMapID, mapID)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ResetFBLinePosX, posX)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ResetFBLinePosY, posY)
    
    NotifyPrepareChangeMap(curPlayer, mapID, funcLineID)
    NotifyStartChangeMap(curPlayer)
    
    ## ·¢ËÍ 04 01 ÈËÎïËùÔڵij¡¾°³õʼ»¯#tagPlayerMapInit
    playerMapInit = ChNetSendPack.tagPlayerMapInit()
    playerMapInit.Clear()
    playerMapInit.MapID = mapID
    playerMapInit.PosX = posX
    playerMapInit.PosY = posY
    NetPackCommon.SendFakePack(curPlayer, playerMapInit)
    
    curPlayer.SetSight(0) # ÊÓÒ°ÖÃ0£¬Çгɹ¦ºó»Ö¸´ÊÓÒ°£¬·ÀÖ¹½ÓÏÂÀ´ÌáǰÉèÖÃ×ø±êµ¼ÖÂǰ¶ËÊÓÒ°Ë¢ÐÂÒì³£
    curPlayer.ResetPos(posX, posY) # ÕâÀïÖ±½ÓÉèÖÃ×ø±ê£¬·Àֹǰ¶Ëδ¼ÓÔØ³¡¾°³É¹¦µôÏßµ¼ÖÂÖØµÇºó×ø±ê´íÎó
    SetFBFuncLineID(curPlayer, funcLineID) # ÕâÀïÖ±½ÓÉèÖóÉÄ¿±ê¹¦ÄÜÏß·ID£¬·Àֹǰ¶Ëδ¼ÓÔØ³¡¾°³É¹¦µôÏßµ¼ÖÂÖØµÇºó¼ÓÔØ³¡¾°Òì³£
    
    ## ·¢ËÍ 01 09 ·þÎñÆ÷×¼±¸¾ÍÐ÷#tagServerPrepareOK
    prepareOK = ChNetSendPack.tagServerPrepareOK()
    prepareOK.Clear()
    NetPackCommon.SendFakePack(curPlayer, prepareOK)
    return
##Íæ¼ÒÇл»µ½Ö¸¶¨¸±±¾ID
# @param curPlayer Íæ¼ÒʵÀý
# @param mapID µØÍ¼ID
# @param posX ×ø±êX
# @param posY ×ø±êY
# @param takeTruck ÊÇ·ñ´øïÚ³µ
# @param FBID ¸±±¾ID, ÐéÄâÏß·ID
# @param msg Я´ýÐÅÏ¢
# @param canLock ÊÇ·ñËø¶¨Íæ¼Ò
# @param funcLineID ¸±±¾¹¦ÄÜÏß·ID£¬ÓÉǰ¶ËÇëÇó
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÇл»µ½Ö¸¶¨¸±±¾ID
def PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, takeTruck, fbID=0, msg='', canLock=True, funcLineID=0, enterFBFree=False):
    '''
    ²ÎÊý˵Ã÷:
        @param fbID:
            ´óÓÚ0µÄÕûÊý:
                Èç¹û²ÎÊýmapIDÖ¸¶¨µÄµØÍ¼´æÔÚfbIDÖ¸¶¨µÄ·ÖÏߣ¬ÔòÖ±½Ó´«Ë͵½²ÎÊýmapIDËùÖ¸¶¨µÄµØÍ¼µÄfbIDËùÖ¸¶¨µÄ·ÖÏߣ¬·ñÔòÔÚËùÓдæÔڵķÖÏßÖУ¬Ëæ»úѡһÌõ·ÖÏß´«Èë¡£fbIDµÄ¼ÆËã¼ûÏÂÃæfbID=-1µÄ˵Ã÷¡£
            -1£º
                ½Ó¿ÚÄÚ²¿×Ô¶¯Ìæ»»³Éµ±Ç°fbID£¬´«Èë²ÎÊýmapIDËùÖ¸¶¨µÄµØÍ¼£¨ÕâÀï²ÎÊýmapIDÆäʵÊÇDataMapID£©µÄͬһfbIDµÄµØÍ¼(Èç¹ûÓУ¬Ã»ÓÐÔòËæ»ú)¡£
                Ï־͵±Ç°fbIDµÄ¼ÆËã,¾ÙÀý˵Ã÷,¼ÙÉèµØÍ¼AºÍµØÍ¼BÔÚMapID.txtÅäÖÃÈçÏ£º
                MapName     MapID   DataMapID FBCount
                µØÍ¼A         101     101     3
                µØÍ¼B         102     101     3 
                ¼´µØÍ¼AºÍµØÍ¼BÓй²Í¬µÄDataMapID,ÄÇôµØÍ¼B½ø³ÌÄÚ²¿µÄµÚÒ»Ìõ·ÖÏߵĿͻ§¶ËID¾ÍÊÇ3(ËùÓзÖÏߵĿͻ§¶Ë·ÖÏßID:0¡¢1¡¢2¡¢3¡¢4¡¢5)
            -2£º
                Ö±½ÓËæ»ú´«µ½²ÎÊýmapIDËùÖ¸¶¨µÄµØÍ¼µÄijһÄÚ²¿·ÖÏߣ¬ÕâÀïµÄijһÄÚ²¿·ÖÏßÏÞÓÚMapID.txtÖÐmapIDΪ´«Èë²ÎÊýmapIDµÄµØÍ¼½ø³ÌµÄ·ÖÏß¡£
    
        @param funcLineID: ¹¦ÄÜÏß·ID
    '''
    tick = GameWorld.GetGameWorld().GetTick()
    lastTransTick = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TransTick)
    #Ôݶ¨1Ãë
    if tick - lastTransTick < 1000:
        GameWorld.Log("Íæ¼ÒÇÐͼCDÖÐ: mapID=%s,posX=%s,posY=%s,takeTruck=%s,fbID=%s,msg=%s,funcLineID=%s,tick=%s,lastTransTick=%s" 
                      % (mapID, posX, posY, takeTruck, fbID, msg, funcLineID, tick, lastTransTick), curPlayer.GetPlayerID())
        NotifyCode(curPlayer, "MapMoveCD")
        return
    curPlayer.SetDict(ChConfig.Def_PlayerKey_TransTick, tick)
    
    sceneMapID = mapID
    if GameWorld.GetMap().GetMapFBTypeByMapID(mapID) != IPY_GameWorld.fbtNull:
        # ¸±±¾¹¦Äܳ¡¾°µØÍ¼
        mapID = FBCommon.GetRecordMapID(mapID)
        fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, funcLineID)
        if fbLineIpyData:
            sceneMapID = fbLineIpyData.GetMapID()
            
    # µØÍ¼·ÖÁ÷, ¼õÉÙµ¥µØÍ¼Ñ¹Á¦
    FBMapShuntDict = ReadChConfig.GetEvalChConfig("FBMapShunt")
    if mapID in FBMapShuntDict:
        shuntList = FBMapShuntDict[mapID]
        if shuntList:
            sceneMapID = random.choice(shuntList)
            GameWorld.DebugLog("µ¥È˵ØÍ¼·ÖÁ÷ sceneMapID=%s" % sceneMapID)
            
    #´«ËÍʱ, Ëø¶¨Íæ¼Ò, ´«Ëͳɹ¦, ÔÚÄ¿±êµØÍ¼½âËø, ´«ËÍʧ°Ü, ÔÚ´«Ëͻص÷º¯ÊýPlayerChangeMapFailCallbackÖнâËø
    if canLock:
        curPlayer.BeginEvent()
    
    if not takeTruck:
        #È¡Ïû×Ô¶¯ÔËïÚ
        PlayerTruck.SetAutoTruckState(curPlayer, ShareDefine.Def_Out_Truck)
    #GameWorld.Log(1, "SetXP=%s"%(curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RecordXPValue)))
    #curPlayer.SetXP(curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RecordXPValue))
    #»ñÈ¡¸±±¾´«È븱±¾ÐèҪЯ´øµÄÐÅÏ¢
    msg = FBLogic.GetPlayerResetWorldPosFBMsg(curPlayer, mapID, funcLineID)
    
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqFBFuncLine, funcLineID)
    GameWorld.Log("Íæ¼ÒÇëÇó¿ªÊ¼ÇÐͼ: sceneMapID=%s,posX=%s,posY=%s,takeTruck=%s,fbID=%s,msg=%s,funcLineID=%s,tick=%s,lastTransTick=%s" 
                  % (sceneMapID, posX, posY, takeTruck, fbID, msg, funcLineID, tick, lastTransTick), curPlayer.GetPlayerID())
    if enterFBFree:
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_EnterFBFree, 1)
        GameWorld.DebugLog("    ±¾´ÎÃâ·Ñ½øÈ븱±¾!")
    curPlayer.ResetWorldPosReq(sceneMapID, posX, posY, takeTruck, fbID, msg)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ChangeMapID, sceneMapID)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ChangeLineID, max(0, fbID))
    
    #ÇеØÍ¼´¦ÀíÍæ¼ÒʱÖÓ¾ÀÕýÎÊÌ⣨ÐèҪһֱͨ¹ýÍæ¼ÒʱÖÓ¼ÆËãµÄ£©
    RefreshPlayerTick(curPlayer)
    NotifyPrepareChangeMap(curPlayer, sceneMapID, funcLineID)
    return
# ֪ͨ׼±¸Çл»µØÍ¼
def NotifyPrepareChangeMap(curPlayer, sceneMapID, funcLineID):
    curPlayer.SetVisible(False)
    sendPack = ChPyNetSendPack.tagMCPrepareChangeMap()
    sendPack.Clear()
    sendPack.MapID = GameWorld.GetMapDataMapID(sceneMapID)
    sendPack.FuncLineID = funcLineID
    
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    GameWorld.Log("×¼±¸Çл»µØÍ¼", curPlayer.GetID())
    return
# ֪ͨ¿ªÊ¼Çл»µØÍ¼
def NotifyStartChangeMap(curPlayer):
    sendPack = ChPyNetSendPack.tagMCStartChangeMap()
    sendPack.Clear()
    sendPack.MapID = GameWorld.GetMapDataMapID(curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeMapID))
    sendPack.FuncLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqFBFuncLine)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    
    GameWorld.Log("֪ͨ¿ªÊ¼Çл»µØÍ¼", curPlayer.GetID())
    return
#---------------------------------------------------------------------
##Íæ¼Ò»»Ïß
# @param curPlayer Íæ¼ÒʵÀý
# @param changLineID Ïß·ID
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò»»Ïß
def PlayerChangeLine(curPlayer, changLineID):
    #---µØÍ¼·ÖÏß¼ì²é---
    if GameWorld.GetGameWorld().GetLineID() == changLineID:
        GameWorld.ErrLog('changLineID SameLine = %s' % (changLineID))
        return
    
    #---µØÍ¼ÊôÐÔ¼ì²é---
    gameMap = GameWorld.GetMap()
    
    #1. Ö»ÓÐÆÕͨµØÍ¼²ÅÄÜ»»Ïß
    if gameMap.GetMapFBType() != IPY_GameWorld.fbtNull:
        #GeRen_liubo_180377    ¶Ô²»Æð£¬Ä¿Ç°¸ÃµØÍ¼Ã»Óпª·Å·ÖÁ÷£¬ÎÞ·¨Çл»Ïß·!  256 -
        NotifyCode(curPlayer, "GeRen_liubo_180377")
        return
    
    #2. »»ÏßµÄÄ¿µÄµØ±ØÐë´æÔÚ
    if changLineID >= gameMap.GetMaxFbCount():
        GameWorld.ErrLog("»»ÏßµÄÄ¿µÄµØ²»´æÔÚ = %s, %s" % (changLineID, gameMap.GetMaxFbCount()), curPlayer.GetID())
        return
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_PlayChangeLineID, changLineID + 1)
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FuncChangeLineID, 0)
    NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_HighChangeLineID, 0)
    
    #---¿ªÊ¼Çл»Ïß·---
    PlayerResetWorldPosFB(curPlayer, curPlayer.GetMapID(), curPlayer.GetPosX(), curPlayer.GetPosY(), False, changLineID)
    
    GameWorld.Log('Íæ¼Ò = %s Çл»·ÖÏß = %s, Ëø×¡' % (curPlayer.GetName(), changLineID), curPlayer.GetID())
    return
#---------------------------------------------------------------------
##Íæ¼ÒÇл»µØÍ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param mapID µØÍ¼ID
# @param posX ×ø±êX
# @param posY ×ø±êY
# @param takeTruck ÊÇ·ñЯ´øïÚ³µ
# @param lineID Ïß·ID -1´ú±íµ±Ç°Ïß
# @param msg Çл»µØÍ¼Ð¯´øµÄÐÅÏ¢
# @param canLock ÊÇ·ñ¿ÉÒÔËø¶¨Íæ¼Ò(´«Ë͵㲻¿ÉËø¶¨, ÒòΪҪ¿çµØÍ¼Ñ°Â·)
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÇл»µØÍ¼
def PlayerResetWorldPos(curPlayer, mapID, posX, posY, takeTruck, lineID=-1, msg='', canLock=True, exData1=0):
    #¸ü¸Ä: ËÀÍöÔÊÐíÇл»µØÍ¼, ÔÚ¸±±¾Öб»¹Ö´òËÀ, ¸±±¾Ê±¼äµ½, »ØÊÕ¸±±¾
#    if GameObj.GetHP(curPlayer) <= 0 :
#        GameWorld.Log("ËÀÍöÎÞ·¨Çл»µØÍ¼")
#        return
    
    gameWorld = GameWorld.GetGameWorld()
    shuntLineID = GetResetWorldPosShuntLineID(curPlayer, gameWorld.GetMapID(), gameWorld.GetLineID(), mapID, lineID, exData1) # ·ÖÁ÷Ïß·ID
    GameWorld.DebugLog("·ÖÁ÷ mapID=%s,lineID=%s,shuntLineID=%s" % (mapID, lineID, shuntLineID), curPlayer.GetPlayerID())
    
    #---ͬµØÍ¼ID, ͬ·ÖÏß, ½öÇл»×ø±ê---
    #lingID = -1, ´ú±íĬÈϵ±Ç°Ïß, ÈçÖ÷³Ç2´«Ëͽ£×Ú, µ½´ï½£×Ú2
    if gameWorld.GetMapID() == mapID and (shuntLineID == -1 or gameWorld.GetLineID() == shuntLineID):
        if exData1:
            #bossµÄÓÃmove£¬Í¨ÖªÇ°¶Ë£¬ÓÉǰ¶Ë·¢Æðmove
            ChPlayer.NotifyPlayerMove(curPlayer, posX, posY, exData1)
        else:
            #ÖØÖÃ×ø±ê
            GameWorld.ResetPlayerPos(curPlayer, posX, posY)
        #@bug: ÔÚ°ÚÌ¯Çø¿ìËÙ´«ËÍÖÁ·Ç°ÚÌ¯Çø, ¿ÉÒÔ°Ú̯, ÕâÀïË¢ÐÂһϳ¡¾°Buff
        SkillShell.ProcessMapBuff(curPlayer, GameWorld.GetGameWorld().GetTick())
        return
    
    #---²»Í¬µØÍ¼IDÇл»µØÍ¼---
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, takeTruck, shuntLineID, msg, canLock)
    
    #Èç¹ûÊÇ·þÎñÆ÷ÖÐ×îºóÒ»¸öÈËÀ뿪, Ôò¹Øµô¸±±¾
    GameWorldProcess.OnPlayerLeaveMapCloseFB()
    return
def GetResetWorldPosShuntLineID(curPlayer, curMapID, curLineID, tagMapID, tagLineID, bossID=0):
    '''»ñÈ¡ÇÐͼÏß·ID
    ÇÐÏßÓÐÈýÖÖÇé¿ö
    1. Íæ¼ÒÊÖ¶¯Çл»Ïß·£¬ÓÅÏȼ¶×î¸ß
            ¼Ç¼key  Def_Player_Dict_PlayChangeLineID£¬ ÀëÏß³¬¹ý±£»¤Ê±¼äºóÖØÖã¬È·±£¶ÏÏßÖØÁ¬Õý³£¼´¿É
            
    2. ¹¦ÄÜÇл»µ½Ö¸¶¨Ïß·£¬Èç´òboss¡¢´«Ë͵½Ä¿±êÍæ¼ÒÏß·£¨±»»÷ɱÇйýÈ¥°ï棩
            ¼Ç¼key  Def_Player_Dict_FuncChangeLineID£¬ ÀëÏß³¬¹ý±£»¤Ê±¼äºóÖØÖã¬È·±£¶ÏÏßÖØÁ¬Õý³£¼´¿É
            
    3. ³£¹æÇÐͼ
            Ïß·ѡÔñÓÅÏȼ¶: ÊÖ¶¯ÇÐÏ߼Ǽ > ¹¦ÄÜÇÐÏ߼Ǽ > ¸ßµÍÇÐÏ߼Ǽ > ϵͳ·ÖÁ÷ÇÐÏß¹æÔò
            
            ϵͳ·ÖÁ÷ÇÐÏß¹æÔò: µ±Ç°µØÍ¼Ïß· ¶ÔÓ¦ Ä¿±êµØÍ¼Ïß·ÈËÊý Èç¹ûµ½´ï¶î¶¨Öµ²Å½øÐзÖÁ÷£¬·ÖÁ÷µ½ÈËÊý½ÏÉÙµÄÏß·
            
        ÌØÊâboss·ÖÁ÷: 
        @param bossID: ·ÖÁ÷bossID
    '''
    if PlayerTJG.GetIsTJG(curPlayer):
        GameWorld.DebugLog("ÍÑ»úµÄÍæ¼Ò²»´¦Àí·ÖÁ÷£¡", curPlayer.GetPlayerID())
        return tagLineID
    if GameWorld.IsCrossServer():
        return tagLineID
    # ·Ç³£¹æµØÍ¼Ö®¼äµÄÇл»²»´¦Àí
    if curMapID not in PyGameData.g_commMapLinePlayerCountDict or tagMapID not in PyGameData.g_commMapLinePlayerCountDict:
        return tagLineID
    tagLinePlayerCountDict = PyGameData.g_commMapLinePlayerCountDict[tagMapID] # ´Ë·ÖÏß°üº¬ËùÓзÖÏߣ¬º¬Î´¿ª·ÅµÄ¼°»î¶¯·ÖÏß
    
    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)
    highChangeLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_HighChangeLineID)
    
    GameWorld.DebugLog("´¦Àí·ÖÁ÷,curMapID=%s,curLineID=%s,tagMapID=%s,tagLineID=%s,bossID=%s" 
                       % (curMapID, curLineID, tagMapID, tagLineID, bossID), playerID)
    # ÓÐÖ¸¶¨Ïß·£¬Ö±½Ó·µ»Ø£¬²»·ÖÁ÷
    if tagLineID != -1:
        # »¹Ã»Ö¸¶¨·ÖÏ߼ǼµÄÔòÒª¼Ç¼£¬ÒѾ¼Ç¼¹ýµÄ²»Öظ´¼Ç¼£¬Ö±µ½Ï´λص½ÔÏß·ºó²ÅÖØÖÃ0
        if not playChangeLineID and not funcChangeLineID and not highChangeLineID:
            NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FuncChangeLineID, curLineID + 1)
            GameWorld.DebugLog("¹¦ÄÜÖ¸¶¨Çл»Ä¿±êÏß·£¬¼Ç¼µ±Ç°Ïß·ºóÐøÇÐÏß±¸ÓÃ! curLineID=%s,tagLineID=%s" % (curLineID, tagLineID), playerID)
            
        if bossID and NPCCommon.IsMapNeedBossShunt(tagMapID):
            bossShuntLineID = __GetBossShuntLineID(curPlayer, curMapID, curLineID, tagMapID, bossID, tagLinePlayerCountDict.keys())
            if bossShuntLineID != -1:
                tick = GameWorld.GetGameWorld().GetTick()
                GameWorld.DebugLog("·ÖÁ÷boss, bossID=%s,bossShuntLineID=%s" % (bossID, bossShuntLineID), playerID)
                NPCCommon.AddBossShuntRelatedPlayer(curPlayer, tagMapID, bossShuntLineID, bossID, tick)
                return bossShuntLineID
        return tagLineID
    
    if curMapID == tagMapID:
        GameWorld.DebugLog("ͬµØÍ¼Çл»×ø±ê²»´¦Àí·ÖÁ÷£¡", playerID)
        return tagLineID
    
    # ¿ÉÒÔÓÃÀ´³£¹æ·ÖÁ÷µÄÏß·ÈËÊý×ÖµäÐÅÏ¢, ²¢²»ÊÇËùÓÐÏß·¶¼¿ÉÒÔÓÃÀ´×öÈËÊý·ÖÁ÷µÄ£¬±ÈÈçÖÐÁ¢µØÍ¼ÓжàÌõÏßÓÃÀ´·ÖÁ÷boss£¬µ«ÊÇÖ»ÓÐ1ÌõÏß¿ÉÓÃÀ´×ö³£¹æµÄÈËÊý·ÖÁ÷
    mapLineDict = IpyGameDataPY.GetFuncCfg("MapLine", 1)
    if tagMapID in mapLineDict:
        tagMapMaxLine = mapLineDict[tagMapID]
        tagLinePlayerCountShuntDict = {}
        for k, v in tagLinePlayerCountDict.items():
            if k >= tagMapMaxLine:
                continue
            tagLinePlayerCountShuntDict[k] = v
    else:
        tagLinePlayerCountShuntDict = tagLinePlayerCountDict
        tagMapMaxLine = len(tagLinePlayerCountShuntDict)
    GameWorld.DebugLog("Ä¿±êµØÍ¼¿ÉÓ÷ÖÁ÷Ïß·ÈËÊýÐÅÏ¢: tagMapID=%s,%s" % (tagMapID, tagLinePlayerCountShuntDict))
    
    # ÓÐÖ÷¶¯Çл»¹ý
    if playChangeLineID and playChangeLineID <= len(tagLinePlayerCountShuntDict):
        GameWorld.DebugLog("ÓÐÖ÷¶¯Çл»¹ýÏß·!playChangeLineID=%s" % playChangeLineID, playerID)
        return playChangeLineID - 1
    
    # ¹¦ÄÜÓÐÖ¸¶¨Ïß·¹ý
    if funcChangeLineID and funcChangeLineID <= len(tagLinePlayerCountShuntDict):
        GameWorld.DebugLog("¹¦ÄÜÓÐÖ¸¶¨¹ýÏß·ÀúÊ·Ïß·,funcChangeLineID=%s" % funcChangeLineID, playerID)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FuncChangeLineID, 0) # ´¥·¢»ØÔÏß·ºóÖØÖÃ
        return funcChangeLineID - 1
    
    # ÓиßÏßÇеÍÏ߼Ǽ
    if highChangeLineID and highChangeLineID <= len(tagLinePlayerCountShuntDict):
        GameWorld.DebugLog("ÓиßÏßÇеÍÏßÀúÊ·Ïß·,highChangeLineID=%s" % highChangeLineID, playerID)
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_HighChangeLineID, 0) # ´¥·¢»ØÔÏß·ºóÖØÖÃ
        return highChangeLineID - 1
    
    if curLineID not in tagLinePlayerCountShuntDict:
        GameWorld.DebugLog("Ä¿±êµØÍ¼²»´æÔÚ¸ÃÏß·,curLineID=%s" % curLineID, playerID)
        shuntLineID = __GetShuntLineID(curPlayer, tagMapID, tagLinePlayerCountShuntDict)
        
        # Èç¹ûûÓд¥·¢·ÖÁ÷£¬ÔòÐè¼ÇÂ¼Íæ¼Ò´Ó¸ßÏß·µØÍ¼Çл»µ½µÍÏß·µØÍ¼Ê±µÄ¸ßÏß·ID
        if shuntLineID == -1 and not playChangeLineID and not funcChangeLineID and not highChangeLineID:
            NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_HighChangeLineID, curLineID + 1)
            GameWorld.DebugLog("¸ßÏßÇеÍÏߣ¬¼Ç¼µ±Ç°Ïß·ºóÐøÇÐÏß±¸ÓÃ! curLineID=%s,tagLineID=%s" % (curLineID, tagLineID), playerID)
            
    else:
        shuntLineID = __GetShuntLineID(curPlayer, tagMapID, tagLinePlayerCountShuntDict, curLineID)
        
    if shuntLineID == -1 and (curLineID + 1) > tagMapMaxLine:
        shuntLineID = tagMapMaxLine - 1
        GameWorld.DebugLog("³£¹æ·ÖÁ÷ºóµÄlineIDΪ-1£¬µ«ÊÇÄ¿±êµØÍ¼µ±Ç°Ïß·²»¿ÉÓ㡲»¿É´«Ë͵½¸ÃÏß·£¡curLineID=%s + 1 > tagMapMaxLine(%s), Ç¿ÖÆ·ÖÁ÷µ½Ïß·(shuntLineID=%s)" 
                           % (curLineID, tagMapMaxLine, shuntLineID))
        
    return shuntLineID
def __GetShuntLineID(curPlayer, tagMapID, tagLinePlayerCountShuntDict, curLineID=None):
    # ÒÔÏÂ×ßϵͳ×Ô¶¯·ÖÁ÷Âß¼
    playerID = curPlayer.GetPlayerID()
    if curPlayer.GetLV() > IpyGameDataPY.GetFuncCfg("SetWorldPosShunt", 2):
        GameWorld.DebugLog("³¬¹ýÖ¸¶¨µÈ¼¶²»·ÖÁ÷", playerID)
        return -1
    
    mapShuntDict = IpyGameDataPY.GetFuncEvalCfg("SetWorldPosShunt", 1) # {mapID:ÈËÊý, ...}
    if tagMapID not in mapShuntDict:
        GameWorld.DebugLog("Ä¿±êµØÍ¼²»ÐèÒª·ÖÁ÷", playerID)
        return -1
    lineMaxPlayerCount = mapShuntDict[tagMapID]
    
    if curLineID != None:
        tagLinePlayerCount = tagLinePlayerCountShuntDict[curLineID]
        if tagLinePlayerCount < lineMaxPlayerCount:
            GameWorld.DebugLog("δ´ïµ½¶î¶¨ÈËÊýÖµ,²»Ó÷ÖÁ÷,curLineID=%s,Ä¿±êµØÍ¼µ±Ç°Ïß·ÈËÊý: %s/%s" 
                               % (curLineID, tagLinePlayerCount, lineMaxPlayerCount), playerID)
            return -1
        
    # ·ÖÁ÷µ½ÈËÊý½ÏÉÙµÄÏß·
    linePlayerList = [[playerCount, lineID] for lineID, playerCount in tagLinePlayerCountShuntDict.items()]
    linePlayerList.sort() # ÉýÐòÅÅ, ÔòË÷Òý0µÄÏß·Ϊ×î¼ÑÑ¡Ôñ
    shuntLineID = linePlayerList[0][1]
    GameWorld.DebugLog("·ÖÁ÷µ½ÈËÊý½ÏÉÙµÄÏß·,tagMapID=%s,linePlayerList[count,lineID]=%s" % (tagMapID, linePlayerList), playerID)
    return shuntLineID
def __GetBossShuntLineID(curPlayer, curMapID, curLineID, tagMapID, npcID, lineIDList):
    '''»ñȡĿ±êµØÍ¼boss·ÖÁ÷Ïß·
                ¸ù¾ÝÈËÊý·ÖÁ÷Íæ¼Ò£¬ÓÅÏÈ·ÖÅäµ½»î×ŵÄÏß·
                ¶ÓÎéĬÈÏ·ÖÅäµ½¶ÓÎé¶ÓÔ±¶àµÄÄÇÌõÏß
                ÐÖúĬÈÏ·ÖÅ䵽Ŀ±êÍæ¼ÒÏß·£¬ÓÅÏȼ¶×î¸ß
                      
                ǰ¶Ë£º
        1.ÔÚÖÐÁ¢µØÍ¼µÄʱºò£¬ÏÔʾµ±Ç°Ïß·BOSSµÄ״̬
        2.ÔÚ³£¹æµØÍ¼µÄʱºò£¬ÏÔÊ¾Íæ¼Ò»÷ɱBOSSµÄCDʱ¼ä
        3.±¾µØÍ¼²»»»Ïߣ¬60Ãë¹æÔò±£³Ö²»±ä
        4.½øÈëBOSSÇøÓòÀˢÐÂBOSS״̬
        
                Íæ¼ÒÔÚ·ÇÖÐÁ¢µØÍ¼£º
                ±¾µØÍ¼²»»»Ïߣ¬60Ãë¹æÔò±£³Ö²»±ä£¨£©
                
                Íæ¼ÒÔÚÖÐÁ¢µØÍ¼
                ûÓÐ60Ãë¹æÔò
                Ö±½Ó·¢´«ËͰü£¬Óɺó¶Ë¾ö¶¨£¨ÓжÓÔ±ÔÚ²»Í¬Ïß·´òͬһֻboss£¬Ôò´«ËÍ£¬·ñÔòmove£©
    '''
    playerID = curPlayer.GetPlayerID()
    playerTeamID = curPlayer.GetTeamID()
    
    hurtTeamLineID = -1
    hurtTeamMemCount = -1
    
    bossLinePlayerDict = {1:[-1, []], 0:[-1, []]} # {ÊÇ·ñ±»»÷ɱ:[¸Ã״̬ÈËÊý¿ÕµÄÏß·, [[Íæ¼ÒÊý, Ïß·], ...]], ...}
    
    bossLineStateDict = PyGameData.g_bossShuntLineState.get(npcID, {})
    
    haveAliveLine = False # ÊÇ·ñÓлî×ŵÄÏß·
    activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})
    
    GameWorld.DebugLog("Íæ¼Òboss·ÖÁ÷: playerTeamID=%s,tagMapID=%s,npcID=%s,lineIDList=%s,bossLineStateDict=%s,g_bossShuntPlayerInfo=%s" 
                       % (playerTeamID, tagMapID, npcID, lineIDList, bossLineStateDict, PyGameData.g_bossShuntPlayerInfo), playerID)
    if tagMapID in activityMapLineDict:
        activityLineID = max(0, activityMapLineDict[tagMapID] - 1)
        # ·Ç1ÏߵĻÏß·²»²ÎÓë·ÖÁ÷
        if activityLineID != 0 and activityLineID in lineIDList:
            lineIDList.remove(activityLineID)
            GameWorld.DebugLog("    ·Ç1ÏߵĻÏß·²»²ÎÓë·ÖÁ÷: activityLineID=%s,lineIDList=%s" % (activityLineID, lineIDList), playerID)
            
    assistTagPlayerID = GetAssistTagPlayerID(curPlayer)
    for lineID in lineIDList:
        key = (tagMapID, lineID)
        # boss·ÖÁ÷Íæ¼ÒÐÅÏ¢{(mapID, lineID):{playerID:[bossID, teamID, relatedTick], ...}, ...}
        shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
        if assistTagPlayerID and assistTagPlayerID in shuntPlayerDict:
            GameWorld.DebugLog("    ·ÖÁ÷µ½ÐÖúÄ¿±êÍæ¼ÒÏß· assistTagPlayerID=%s,lineID=%s" % (assistTagPlayerID, lineID), playerID)
            return lineID
        playerCount = 0
        teamPlayerCount = 0
        for shuntPlayerID, shuntInfo in shuntPlayerDict.items():
            bossID = shuntInfo[0]
            if npcID != bossID:
                continue
            playerCount += 1
            shuntTeamID = shuntInfo[1]
            if playerTeamID and playerTeamID == shuntTeamID and shuntPlayerID != playerID:
                teamPlayerCount += 1
        
        if teamPlayerCount and teamPlayerCount > hurtTeamMemCount:
            hurtTeamMemCount = teamPlayerCount
            hurtTeamLineID = lineID
            
        lineIsAlive = bossLineStateDict.get(lineID, 0)
        lineBossIsDead = 1 if not lineIsAlive else 0 # µ±Ç°Ïß·bossÊÇ·ñËÀÍö
        emptyLineID, linePlayerCountList = bossLinePlayerDict[lineBossIsDead]
        if not playerCount and emptyLineID == -1:
            emptyLineID = lineID
        linePlayerCountList.append([playerCount, lineID])
        bossLinePlayerDict[lineBossIsDead] = [emptyLineID, linePlayerCountList]
        
        if not lineBossIsDead:
            haveAliveLine = True
            
        GameWorld.DebugLog("    lineID=%s,lineBossIsDead=%s,playerCount=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" 
                           % (lineID, lineBossIsDead, playerCount, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
        
    if hurtTeamLineID >= 0:
        GameWorld.DebugLog("    ·ÖÁ÷µ½¶ÓÓÑÈËÊý¶àµÄÏß· hurtTeamLineID=%s" % hurtTeamLineID, playerID)
        return hurtTeamLineID
    
    if curMapID == tagMapID and curMapID in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4):
        GameWorld.DebugLog("    ÖÐÁ¢µØÍ¼ÔÚ±¾µØÍ¼ÖÐĬÈϵ±Ç°Ïß· curLineID=%s" % curLineID, playerID)
        return curLineID
    
    shuntBossIsDead = 0 if haveAliveLine else 1 # ÓÅÏÈ·ÖÁ÷µ½»î×ŵÄÏß·
    GameWorld.DebugLog("    boss״̬¶ÔÓ¦Ïß·ÈËÊý: haveAliveLine=%s, ״̬key0Ϊ»î×Å: %s" % (haveAliveLine, bossLinePlayerDict))
    emptyLineID, linePlayerCountList = bossLinePlayerDict[shuntBossIsDead]
    linePlayerCountList.sort() # ÉýÐò
    playerCount, minPlayerCntLineID = linePlayerCountList[0]
    bossShuntPlayerCountMax = IpyGameDataPY.GetFuncCfg("BossShunt", 2)
    if playerCount >= bossShuntPlayerCountMax and emptyLineID >= 0:
        GameWorld.DebugLog("    ·ÖÁ÷µ½¿ÕÐÂÏß· shuntBossIsDead=%s,emptyLineID=%s" % (shuntBossIsDead, emptyLineID), playerID)
        return emptyLineID
    
    GameWorld.DebugLog("    ·ÖÁ÷µ½ÈËÊý×îÉÙµÄÏß· shuntBossIsDead=%s,minPlayerCntLineID=%s,linePlayerCountList=%s" 
                       % (shuntBossIsDead, minPlayerCntLineID, linePlayerCountList), playerID)
    return minPlayerCntLineID
#---------------------------------------------------------------------
##È¡ºÏ·¨ÖØÉúµã
# @param curPlayer Íæ¼ÒʵÀý
# @param posX ÖØÉúµãx×ø±ê
# @param posy ÖØÉúµãy×ø±ê
# @param round ÖØÉúµã·¶Î§
# @return ÖØÉúµã(×ø±êx£¬ ×ø±êy)
# @remarks 
def __GetLegitRebornPoint(curPlayer, posX, posY, round):
    rebornPosX = 0
    rebornPosY = 0
    
    curMapID = curPlayer.GetMapID()
    
    gameMap = GameWorld.GetMap()
    
    #Ìí¼Ó×ø±êµãÒì³£¼ì²é(ÖØÉúµã×ø±ê³¬¹ýµØÍ¼±ß½ç)
    if not gameMap.IsValidPos(posX, posY):
        GameWorld.ErrLog('ÖØÉúµãÒì³££¬³¬¹ýµØÍ¼(%s)±ß½ç posX = %s, posY = %s, round = %s' \
                         % (curMapID, posX, posY, round))
    
    else:
        # Ëæ»úÈ¡µ½·ÇÕϰµã
        rebornPosX, rebornPosY = GameMap.GetNearbyPosByDis(posX, posY, round)
            
        #²¼µÄÖØÉúµã·¶Î§ÄÚÕÒ²»µ½·ÇÕϰµã
        if rebornPosX <= 0 or rebornPosY <= 0:
            GameWorld.Log("ÖØÉúµã·¶Î§ÄÚÕÒ²»µ½¸ÃµØÍ¼(%s)µÄ·ÇÕÏ°ÖØÉúµã posX = %s, posY = %s, round = %s" % \
                          (curMapID, posX, posY, round), curPlayer.GetPlayerID())
    
    return (rebornPosX, rebornPosY)
                    
#---------------------------------------------------------------------
##Ë¢ÐÂÍæ¼ÒµÄÖØÉúµãÐÅÏ¢
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ë¢ÐÂÍæ¼ÒµÄÖØÉúµãÐÅÏ¢
def RefreshRebornPoint(curPlayer, tick):
    #---¸´»îµãË¢ÐÂÅжÏ˳Ðò1.µØÍ¼²¼¸´»îµã 2.tagChinMap.txtÄÚ¸´»îµã 3.´´½¨½ÇÉ«³õʼ³öÉúµã---
    
    gameMap = GameWorld.GetMap()
    
    # ³õʼ»¯ÖØÉúµØÍ¼Îªµ±Ç°Íæ¼ÒËùÔÚµØÍ¼
    rebornMapID = curPlayer.GetMapID()
    rebornPosX = curPlayer.GetRebornPosX()
    rebornPosY = curPlayer.GetRebornPosY()
    
    #---µØÍ¼Éϲ¼µÄÖØÉúµãÅжÏ---
    
    # µØÍ¼ÉÏÊÇ·ñÓв¼¸´»îˢеã
    hasBornRefreshPoint = True
    
    gameData = GameWorld.GetGameData()
    bornRefreshCount = gameData.GetBornRefreshCount()
    #Ò»°ãµØÍ¼²¼µÄÖØÉúµãÁбí,¸ù¾Ý¹ú¼®É¸Ñ¡
    bornList = []
    #¸±±¾µØÍ¼²¼µÄÖØÉúµãÁбí,²»É¸Ñ¡
    fbBornList = []
    
    # ûÓв¼ÖØÉúµã
    if not bornRefreshCount:
        GameWorld.Log("´ËµØÍ¼Ã»ÓÐÖØÉúµã", curPlayer.GetPlayerID())
        hasBornRefreshPoint = False
    else:
        #´´½¨ÖØÉúµãÁбí
        for i in range(0, bornRefreshCount):
            bornRefreshPoint = gameData.GetBornRefreshByIndex(i)
            fbBornList.append(i)
            
            if GameWorld.IsSameCountry(curPlayer, bornRefreshPoint):
                bornList.append(i)
    
        if not bornList:
            GameWorld.Log("´ËµØÍ¼Ã»ÓкÏÊÊÍæ¼ÒµÄÖØÉúµã", curPlayer.GetPlayerID())
            hasBornRefreshPoint = False
    #---¸ÃµØÍ¼Óв¼ÖØÉúˢеã---
    if hasBornRefreshPoint:
        # Ëæ»ú»ñÈ¡ÖØÉúˢеã
        bornIndex = random.choice(bornList)
        bornRefreshPoint = gameData.GetBornRefreshByIndex(bornIndex)
        
        bRP_PosX = bornRefreshPoint.GetPosX()
        bRP_PosY = bornRefreshPoint.GetPosY()
        bRP_RoundPos = bornRefreshPoint.GetRound()
        
        rebornPosX, rebornPosY = __GetLegitRebornPoint(curPlayer, bRP_PosX, bRP_PosY, bRP_RoundPos)
        
        #²¼µÄÖØÉúµã·¶Î§ÄÚÕÒ²»µ½ºÏ·¨ÖØÉúµã
        if rebornPosX <= 0 or rebornPosY <= 0 or rebornMapID <= 0:
            GameWorld.Log("µØÍ¼Éϲ¼µÄÖØÉúµã·¶Î§ÄÚÕÒ²»µ½¸ÃµØÍ¼(%s)µÄºÏ·¨ÖØÉúµã" \
                          % curPlayer.GetMapID(), curPlayer.GetPlayerID())
            # Òì³££¬Éè±ê־ΪFalse,´ÓtagChinMap.txt±íÄÚÕÒ¸´»îµã
            hasBornRefreshPoint = False
    
    # ÔÚtagChinMap.txt±íÄÚÊÇ·ñÄÜÕÒµ½¸´»îµã
    hasBornPointInTxt = True  
    
    #---¸ÃµØÍ¼Ã»ÓÐÖØÉúˢе㣬´ÓtagChinMap.txt±íÄÚÕÒ¸´»îµã---    
    if not hasBornRefreshPoint:
        rebornMapID = gameMap.GetRebornMapID()
        rebornPosX = gameMap.GetRebornMapX()
        rebornPosY = gameMap.GetRebornMapY()
        
        #ÑéÖ¤ÊÇ·ñ±¾µØÍ¼¸´»îµã ½øÐÐÂß¼´¦Àí, ·Ç±¾µØÍ¼¸´»îµãÎÞ·¨Åжϣ¬ ÒªÇó²ß»®Ò»¶¨ÅäÖÃÕýÈ·
        if gameMap.GetMapID() == rebornMapID:
            # Ëæ»úÈ¡µ½·ÇÕϰµã
            rebornPosX, rebornPosY = __GetLegitRebornPoint(curPlayer, \
                                                           rebornPosX, rebornPosY, ChConfig.Def_RebornPos_Area_Range)
        #tagChinMap.txt±íÉÏÕÒ²»µ½ºÏ·¨ÖØÉúµã
        if rebornPosX <= 0 or rebornPosY <= 0 or rebornMapID <= 0:
            GameWorld.Log("tagChinMap.txtÄÚÕÒ²»µ½¸ÃµØÍ¼(%s)µÄºÏ·¨ÖØÉúµã" \
                          % curPlayer.GetMapID(), curPlayer.GetPlayerID())
            hasBornPointInTxt = False
            
    #---ÔÚtagChinMap.txt±íÄÚÒ²ÕÒ²»µ½¸´»îµã,Ö±½ÓÖØÖõ½´´½¨½ÇɫʱµÄ³õʼµã---
    if not hasBornPointInTxt:
        curPlayerJob = curPlayer.GetJob()
        
        #´´½¨Íæ¼ÒλÖöÁ±í{ Ö°Òµ:[(map,x,y),(map1,x1,y1)..] }
        posList = ReadChConfig.GetEvalChConfig('Player_Reborn_Place')
        
        pos = random.choice(posList[curPlayerJob])
        rebornMapID = pos[0]
        bornRange = 1
        rebornPosX = pos[2] + random.randint(-bornRange, bornRange)
        rebornPosY = pos[3] + random.randint(-bornRange, bornRange)
        GameWorld.Log("""tagBornRefresh.txtºÍtagChinMap.txtÄÚ¶¼ÕÒ²»µ½¸ÃµØÍ¼(%s)
µÄºÏ·¨ÖØÉúµã£¬ÉèÖÃÍæ¼ÒÖØÉúµãΪ´´½¨½ÇɫʱµÄ³õʼµã%s-(%s,%s)""" % \
                      (curPlayer.GetMapID(), rebornMapID, rebornPosX, rebornPosY), curPlayer.GetPlayerID())        
                                
    #Íæ¼Ò²»ÔÚ¸±±¾ÖÐ
    if gameMap.GetMapFBType() == IPY_GameWorld.fbtNull:
        # ÉèÖÃÒ»°ãµØÍ¼ÖØÉúµã
        curPlayer.SetRebornMapID(rebornMapID)
        curPlayer.SetRebornPosX(rebornPosX)
        curPlayer.SetRebornPosY(rebornPosY)
        GameWorld.Log("Íæ¼Ò%s,ÉèÖÃĬÈÏÖØÉúµãÍê±Ï mapID = %s-(%s,%s)" % (curPlayer.GetPlayerName(), rebornMapID, rebornPosX, rebornPosY), curPlayer.GetPlayerID())
        return
#===============================================================================
#        #´å³¤¼ÒµÄµØÍ¼ID
#        cunZhangJiaMapID = 21
#    
#        #ÓÐÖØÉúµã
#        #ÐÂÊÖ³¡ÅÂÍæ¼Ò¿¨ËÀÕϰµã£¬ÉèÖÃΪµ±Ç°×ø±ê
#        if curPlayerMapID == cunZhangJiaMapID:
#            curPlayer.SetRebornMapID( curPlayerMapID )
#            curPlayer.SetRebornPosX( curPlayer.GetPosX() )
#            curPlayer.SetRebornPosY( curPlayer.GetPosY() )
#            return
#        
#        #À뿪ÐÂÊÖ³¡¾°ºó£¬ÖØÖÃÒ»´ÎÖØÉúµã£¬·ÀÖ¹Íæ¼ÒÔٻص½ÐÂÊÖ³¡¾°
#        if curPlayerRebornMapID == cunZhangJiaMapID:
#            curPlayer.SetRebornMapID( curPlayerMapID )
#            curPlayer.SetRebornPosX( bornX )
#            curPlayer.SetRebornPosY( bornY )
#            return
#===============================================================================
    
    #ÏÈÉèÖÃĬÈϵĸ±±¾ÖØÉúµã
    curPlayer.SetFBRebornMapID(rebornMapID)
    curPlayer.SetFBRebornPosX(rebornPosX)
    curPlayer.SetFBRebornPosY(rebornPosY)
    GameWorld.Log("Íæ¼Ò%s,ÉèÖø±±¾Ä¬ÈÏÖØÉúµãÍê±Ï mapID = %s-(%s,%s)" % (curPlayer.GetPlayerName(), rebornMapID, rebornPosX, rebornPosY), curPlayer.GetPlayerID())
    
    # ÌØÊ⸱±¾¸´»îµãÂß¼
    FBLogic.OnRebornPlace(curPlayer, fbBornList)
    return
#---------------------------------------------------------------------
##»ñÈ¡¾ôλ
# @param curLV µÈ¼¶
# @return ·µ»ØÖµ, ¾ôλµÈ¼¶
# @remarks »ñÈ¡¾ôλ
def GetRank(curLV):
    if curLV > 0 and curLV < 21:
        return 1
    else:
        return (curLV - 1) / 10
#---------------------------------------------------------------------
##»ñµÃÖ¸¶¨·½Î»ÄÚ¶ÓÎé³ÉÔ±Áбí
# @param curTeam ¶ÓÎéʵÀý
# @param centerX ÆðµãX
# @param centerY ÆðµãY
# @param area ·¶
# @return ·µ»ØÖµ, ³ÉÔ±Áбí
# @remarks »ñµÃÖ¸¶¨·½Î»ÄÚ¶ÓÎé³ÉÔ±Áбí
def GetAreaTeamMember(curTeam, centerX, centerY, area=ChConfig.Def_Team_GetExpScreenDist, isLog=False):   
    playerlist = list()
    if curTeam == None:
        GameWorld.ErrLog("»ñÈ¡¶ÓÎéÇøÓò³ÉÔ±£¬¶ÓÎé²»´æÔÚ£¡")
        return playerlist
    
    playerIDList = []
    #if isLog:
    #    GameWorld.Log("GetAreaTeamMember,teamID=%s,centerX=%s,centerY=%s,area=%s" % (curTeam.GetTeamID(), centerX, centerY, area))
        
    #±éÀú¶ÓÎé,°ë¾¶ÎªÒ»ÆÁ°ëµÄ¾àÀëÄÚµÄËùÓжÓÎé/ÍŶӳÉÔ±£¬¿ÉÒÔ»ñµÃ¾Ñé
    for i in range(0, curTeam.GetMemberCount()):
        curTeamPlayer = curTeam.GetMember(i)
        if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
            #if isLog:
            #    GameWorld.Log("    i=%s,³ÉÔ±²»´æÔÚ!" % (i))
            continue
        
        if GameObj.GetHP(curTeamPlayer) <= 0:
            #if isLog:
            #    GameWorld.Log("    i=%s,³ÉԱѪÁ¿Îª0!playerID=%s" % (i, curTeamPlayer.GetPlayerID()))
            continue
        
        #===========================================================================================
        # # ¶ÓÎéÒÑÓÉÿÌõÐéÄâÏß·¶À×Ô¹ÜÀí£¬´Ë´¦¿É²»ÔÙÅжÏ
        # if curTeamPlayer.GetCopyMapID() != GameWorld.GetGameWorld().GetCopyMapID():
        #    if isLog:
        #        GameWorld.Log("    i=%s,³ÉÔ±ÐéÄâÏß·²»Í¬!playerID=%s,copyMapID=%s,mapCopyMapID=%s" 
        #                      % (i, curTeamPlayer.GetPlayerID(), curTeamPlayer.GetCopyMapID(), GameWorld.GetGameWorld().GetCopyMapID()))
        #    #¸±±¾ID²»Í¬
        #    continue
        #===========================================================================================
        
        if GameWorld.GetDist(centerX, centerY, curTeamPlayer.GetPosX(),
                             curTeamPlayer.GetPosY()) > area:
            #if isLog:
            #    GameWorld.Log("    i=%s,³ÉÔ±²»ÔÚ·¶Î§ÄÚ!playerID=%s,centerPos(%s,%s),playerPos=(%s,%s),area=%s" 
            #                  % (i, curTeamPlayer.GetPlayerID(), centerX, centerY, curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), area))
            continue
        
        playerlist.append(curTeamPlayer)
        playerIDList.append(curTeamPlayer.GetPlayerID())
        
    #if isLog:
    #    GameWorld.Log("    teamAreaPlayerIDList=%s" % (playerIDList))
    return playerlist
def GetMapTeamMember(curTeam):
    ''' »ñȡͬµØÍ¼ÖеĶÓÔ± '''
    
    playerlist = list()
    if curTeam == None:
        return playerlist
    
    for i in xrange(curTeam.GetMemberCount()):
        curTeamPlayer = curTeam.GetMember(i)
        if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
            continue
        playerlist.append(curTeamPlayer)
        
    return playerlist
#---------------------------------------------------------------------
##»ñÈ¡Íæ¼Ò»õ±ÒÊý
# @param curPlayer Íæ¼ÒʵÀý
# @param TYPE_Price ,»õ±ÒÀàÐÍ
# @return
def GetMoney(curPlayer, TYPE_Price):
    
    #½ð×Ó
    if TYPE_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
        return curPlayer.GetGold()
        
    #½ðƱ
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
        return curPlayer.GetGoldPaper()
       
    #Òø×Ó
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Silver_Money:
        return GetSilver(curPlayer)
        
    #񿮱
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Silver_Paper:
        return curPlayer.GetSilverPaper()
    
    #´ú±Ò
    elif TYPE_Price == ShareDefine.TYPE_Price_PayCoin:
        return GetPayCoin(curPlayer)
    
    #×Ô¶¨Òå»õ±Ò
    elif TYPE_Price in ShareDefine.TYPE_Price_CurrencyDict:
        return GetPlayerCurrency(curPlayer, TYPE_Price)
    
    return 0
def GetMoneyReal(curPlayer, moneyType):
    ## »ñÈ¡»õ±Òʵ¼ÊÖµ£¬Ö§³Ö¸ºÖµ
    moneyMinus = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MoneyMinus % moneyType)
    if moneyMinus != 0:
        return -moneyMinus
    return GetMoney(curPlayer, moneyType)
def SetMoney(curPlayer, moneyType, value):
    ## ÉèÖûõ±ÒÖµ£¬Ö§³Ö¸ºÖµ
    if moneyType in ShareDefine.MoneyMinusRefreshDict:
        moneyMinus = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MoneyMinus % moneyType)
        if value < 0:
            if moneyMinus != value:
                SetMoneyMinus(curPlayer, moneyType, value)
            value = 0
        else:
            if moneyMinus != 0:
                SetMoneyMinus(curPlayer, moneyType, 0)
                
    #½ð×Ó
    if moneyType == IPY_GameWorld.TYPE_Price_Gold_Money:
        curPlayer.SetGold(value)
        
    #½ðƱ
    elif moneyType == IPY_GameWorld.TYPE_Price_Gold_Paper:
        curPlayer.SetGoldPaper(value)
        
    #Òø×Ó
    elif moneyType == IPY_GameWorld.TYPE_Price_Silver_Money:
        SetSilver(curPlayer, value)
        
    #񿮱
    elif moneyType == IPY_GameWorld.TYPE_Price_Silver_Paper:
        curPlayer.SetSilverPaper(value)
        
    #´ú±Ò
    elif moneyType == ShareDefine.TYPE_Price_PayCoin:
        SetPayCoin(curPlayer, value)
        
    #×Ô¶¨Òå»õ±Ò
    elif moneyType in ShareDefine.TYPE_Price_CurrencyDict:
        SetPlayerCurrency(curPlayer, moneyType, value)
        
    return
def SetMoneyMinus(curPlayer, moneyType, value):
    value = abs(value) # ´æÖµ¼°Í¨ÖªÊ¹ÓÃÕýÊý
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MoneyMinus % moneyType, value)
    #֪ͨ¿Í»§¶Ë
    if moneyType not in ShareDefine.MoneyMinusRefreshDict:
        return
    refreshType = ShareDefine.MoneyMinusRefreshDict[moneyType]
    if refreshType != None:
        SendPropertyRefresh(curPlayer, refreshType, value)
    return
## »ñÈ¡Íæ¼Ò²Ö¿â½ðÇ®Êý
#  @param curPlayer: Íæ¼ÒʵÀý
#  @param moneyType: ½ðÇ®ÀàÐÍ
#  @return: Íæ¼ÒÉíÉϽðÇ®Êý
def GetWarehouseMoney(curPlayer, moneyType):
    if moneyType == IPY_GameWorld.TYPE_Price_Gold_Money:
        return curPlayer.GetWarehouseGold()
    
    if moneyType == IPY_GameWorld.TYPE_Price_Gold_Paper:
        return curPlayer.GetWarehouseGoldPaper()
    
    if moneyType == IPY_GameWorld.TYPE_Price_Silver_Money:
        return curPlayer.GetWarehouseSilver()
    
    if moneyType == IPY_GameWorld.TYPE_Price_Silver_Paper:
        return curPlayer.GetWarehouseSilverPaper()
    
    GameWorld.ErrLog("GetWarehouseMoney, moneyType:%d Err" % (moneyType))
    return 0
## »ñµÃ×Ô¶¨Òå»õ±Ò£¨»ý·Ö£©
#  @param curPlayer Íæ¼ÒʵÀý
#  @return
def GetPlayerCurrency(curPlayer, currencyType):
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Currency % currencyType)
## ÉèÖÃ×Ô¶¨Òå»õ±Ò£¨»ý·Ö£©
#  @param curPlayer Íæ¼ÒʵÀý
#  @return
def SetPlayerCurrency(curPlayer, currencyType, value):
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Currency % currencyType, value)
    #֪ͨ¿Í»§¶Ë
    NotifyPlayerCurrency(curPlayer, currencyType, value)
    return
def NotifyPlayerCurrency(curPlayer, currencyType, value=-1):
    if currencyType not in ShareDefine.TYPE_Price_CurrencyDict:
        return
    refreshType = ShareDefine.TYPE_Price_CurrencyDict[currencyType]
    if refreshType == None:
        # ²»ÐèҪ֪ͨ¿Í»§¶Ë
        return
    if value < 0:
        value = GetPlayerCurrency(curPlayer, currencyType)
    SendPropertyRefresh(curPlayer, refreshType, value)
    return
# Í¨ÖªÍæ¼ÒËùÓÐ×Ô¶¨Òå»õ±Ò
def NotifyPlayerAllCurrency(curPlayer):
    notifyList = []
    for currencyType in ShareDefine.TYPE_Price_CurrencyDict:
        refreshType = ShareDefine.TYPE_Price_CurrencyDict[currencyType]
        if refreshType == None:
            # ²»ÐèҪ֪ͨ¿Í»§¶Ë
            continue
        
        #´Ë´¦¸ù¾ÝÐèÇóÈôValueΪ0 ¿É²»Í¨Öª¿Í»§¶Ë£¬¾ßÌ幦ÄÜÖÆ×÷Õß¾ö¶¨
        value = GetPlayerCurrency(curPlayer, currencyType)
        notifyStruct = ChPyNetSendPack.tagRefreshType()
        notifyStruct.RefreshType = refreshType
        notifyStruct.Value = value
        notifyList.append(notifyStruct)
        
    # ¸ºÖµ»õ±Ò
    for moneyType, refreshType in ShareDefine.MoneyMinusRefreshDict.items():
        if refreshType == None:
            # ²»ÐèҪ֪ͨ¿Í»§¶Ë
            continue
        value = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MoneyMinus % moneyType)
        if not value:
            continue
        notifyStruct = ChPyNetSendPack.tagRefreshType()
        notifyStruct.RefreshType = refreshType
        notifyStruct.Value = value
        notifyList.append(notifyStruct)
        
    #ÊôÐÔ×éºÏ°ü ֪ͨ×Ô¼º
    sendPack = ChPyNetSendPack.tagObjInfoListRefresh()
    sendPack.Clear()
    sendPack.ObjID = curPlayer.GetID()
    sendPack.ObjType = curPlayer.GetGameObjType()
    sendPack.Count = len(notifyList)
    sendPack.RefreshType = notifyList
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
def NotifyUseMoneyTotal(curPlayer, moneyTypeList=None):
    if moneyTypeList:
        notifyMoneyTypeList = moneyTypeList
    else:
        notifyMoneyTypeList = ShareDefine.UseTotalPriceTypeList
        
    infoList = []
    for moneyType in notifyMoneyTypeList:
        useTotal = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UseMoneyTotal % moneyType)
        if not useTotal and moneyTypeList == None:
            continue
        info = ChPyNetSendPack.tagMCUseMoneyTotal()
        info.MoneyType = moneyType
        info.UseTotal = useTotal
        infoList.append(info)
            
    if not infoList:
        return
    
    clientPack = ChPyNetSendPack.tagMCUseMoneyTotalInfo()
    clientPack.Clear()
    clientPack.InfoList = infoList
    clientPack.Count = len(clientPack.InfoList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
##Íæ¼ÒÊÇ·ñÓÐÇ®¿î
# @param curPlayer Íæ¼ÒʵÀý
# @param TYPE_Price ,»õ±ÒÀàÐÍ
# @param Price ,»õ±Ò¼Û¸ñ
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks Íæ¼ÒÊÇ·ñÓÐÇ®¿î
def HaveMoney(curPlayer, TYPE_Price, Price, needNotify=True):
    if Price < 0:
        return False
    
    needMoneyCount = 0
    notifyCode = ''
    #½ð×ÓÖ§¸¶
    if TYPE_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
        needMoneyCount = curPlayer.GetGold()
        notifyCode = "GoldErr"
        
    #½ðƱ֧¸¶
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
        needMoneyCount = curPlayer.GetGoldPaper()
        notifyCode = "GoldPaperErr"
       
    #Òø×ÓÖ§¸¶
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Silver_Money:
        needMoneyCount = GetSilver(curPlayer)
        notifyCode = "SilverErr"
        
    #ÒøÆ±Ö§¸¶
    elif TYPE_Price == IPY_GameWorld.TYPE_Price_Silver_Paper:
        needMoneyCount = curPlayer.GetSilverPaper()
        notifyCode = "SilverPaperErr"
        
    #´ú±ÒÖ§¸¶
    elif TYPE_Price == ShareDefine.TYPE_Price_PayCoin:
        needMoneyCount = GetPayCoin(curPlayer)
        
    #×Ô¶¨Òå»õ±Ò
    elif TYPE_Price in ShareDefine.TYPE_Price_CurrencyDict:
        needMoneyCount = GetPlayerCurrency(curPlayer, TYPE_Price)
    else:
        GameWorld.Log("¸¶·Ñ½ðÇ®Òì³£ TYPE_Price = %s" % (TYPE_Price), curPlayer.GetPlayerID())
        return False   
    
    if needMoneyCount < Price:
        lackPrice = Price - needMoneyCount # »¹È±¶àÉÙÇ®
        tagMoneyInfo = GetEqualMoneyInfo(TYPE_Price, lackPrice)
        if tagMoneyInfo:
            tagMoneyType, tagMoneyValue = tagMoneyInfo
            if HaveMoney(curPlayer, tagMoneyType, tagMoneyValue, False):
                GameWorld.DebugLog("HaveMoney¿ÉʹÓõȼۻõ±Ò²¹×ã¿Û³ý: TYPE_Price=%s, Price=%s, lackPrice=%s, tagMoneyType=%s, tagMoneyValue=%s" 
                                   % (TYPE_Price, Price, lackPrice, tagMoneyType, tagMoneyValue), curPlayer.GetPlayerID())
                return True
            
    #---Ç®²»¹» ·µ»Ø¼ÙÈç¹ûÐèÒªÌáʾµÄ»° ÌáʾÐÅÏ¢---
    if needMoneyCount < Price:
        if needNotify and notifyCode:
            NotifyCode(curPlayer, notifyCode)
        GameWorld.DebugLog("»õ±Ò²»×ã: TYPE_Price=%s, Price=%s, curMoneyCount=%s" % (TYPE_Price, Price, needMoneyCount))
        return False
    
    return True
def GetEqualMoneyInfo(moneyType, needValue):
    equalMoneyInfo = IpyGameDataPY.GetFuncEvalCfg("EqualValueMoney", 2, {})
    if str(moneyType) not in equalMoneyInfo:
        return
    tagMoneyType = equalMoneyInfo[str(moneyType)]
    exchangeMoneyInfo = IpyGameDataPY.GetFuncEvalCfg("EqualValueMoney", 1, {})
    if str(tagMoneyType) not in exchangeMoneyInfo:
        return
    exchangeInfo = exchangeMoneyInfo[str(tagMoneyType)]
    if moneyType != exchangeInfo[0]:
        return
    multiple = exchangeInfo[1]
    tagMoneyValue = int(math.ceil(needValue / float(multiple)))
    #GameWorld.DebugLog("µÈ¼Û»õ±ÒÐÅÏ¢: moneyType=%s,needValue=%s,multiple=%s,tagMoneyType=%s,tagMoneyValue=%s" 
    #                   % (moneyType, needValue, multiple, tagMoneyType, tagMoneyValue))
    return tagMoneyType, tagMoneyValue
#---------------------------------------------------------------------
##Íæ¼ÒÊÇ·ñÓÐÇ®¿î
# @param curPlayer Íæ¼ÒʵÀý
# @param TYPE_Price ,»õ±ÒÀàÐÍ
# @param Price ,»õ±Ò¼Û¸ñ
# @return ·µ»ØÖµ[[type1,price1], [type2,price2]]
# @remarks Íæ¼ÒÊÇ·ñÓÐÇ®¿î
def HaveMoneyEx(curPlayer, TYPE_Price, Price, needNotify=True):
    if Price < 0:
        return []
    if TYPE_Price == ShareDefine.TYPE_Price_Gold_Paper_Money:
        TYPE_Price = IPY_GameWorld.TYPE_Price_Gold_Money #аæÎÞ°óÓñ£¬ÔÏȰóÓñÔÙÏÉÓñµÄ¿Û·¨¸Ä³É ¿ÛÏÉÓñ 2019/3/26
        #âýÓ¢°æ£º »Ö¸´°óÓñ£¬µ«ÊDz»Ê¹ÓÃÏȰóÓñÔÙÏÉÓñµÄ¹æÔò£¬ÔÀ´ÏȰóÓñÔÙÏÉÓñµÄ¹æÔòÒ»ÑùΪĬÈÏ¿ÛÏÉÓñ 2019/10/8
        
    if TYPE_Price in [IPY_GameWorld.TYPE_Price_Gold_Money, IPY_GameWorld.TYPE_Price_Gold_Paper,
                      IPY_GameWorld.TYPE_Price_Silver_Money, IPY_GameWorld.TYPE_Price_Silver_Paper]:
        if HaveMoney(curPlayer, TYPE_Price, Price, needNotify):
            return [[TYPE_Price, Price]]
        return []
    
    #ÏÈÀñȯÔÙÔª±¦
    elif TYPE_Price == ShareDefine.TYPE_Price_Gold_Paper_Money:
        goldPaper = curPlayer.GetGoldPaper() # Àñȯ
        gold = curPlayer.GetGold() # Ôª±¦
        
        if goldPaper + gold < Price: # Ç®²»¹»
            if needNotify:
                NotifyCode(curPlayer, "GoldErr")
            return []
            
        if goldPaper >= Price: # Ö»ÓÃÀñȯ¾Í¹»ÁË
            return [[IPY_GameWorld.TYPE_Price_Gold_Paper, Price]]
        needGold = Price - goldPaper # ÓÃÍêÀñȯ£¬»¹ÐèÒªÔª±¦
        return [[IPY_GameWorld.TYPE_Price_Gold_Paper, goldPaper], [IPY_GameWorld.TYPE_Price_Gold_Money, needGold]]
#    #ÓÃÕ½Ã˹±Ï×¶È
#    elif TYPE_Price == ShareDefine.TYPE_Price_Family_Contribution:
#        return []
    else:
        GameWorld.Log("¸¶·Ñ½ðÇ®Òì³£ TYPE_Price = %s" % (TYPE_Price), curPlayer.GetPlayerID())
        return []   
    
    return []
#---------------------------------------------------------------------
##Íæ¼Ò¸¶¿î
# @param curPlayer Íæ¼ÒʵÀý
# @param type_Price ,»õ±ÒÀàÐÍ
# @param price ,»õ±Ò¼Û¸ñ
# @param costType ,Ïû·ÑµãÀàÐÍ
# @param infoDict ,À©Õ¹ÐÅÏ¢, ×ÓÏû·Ñ¶ÔÏó¿ÉÒÔͨ¹ýÉèÖÃChConfig.Def_Cost_Reason_SonKey keyÖµ
# @param quantity ,ÊýÁ¿
# @param isMinus ,ÊÇ·ñÔÊÐí¿Û³É¸ºÖµ
# @return ·µ»ØÖµÕæ, ¸¶¿î³É¹¦
# @remarks Íæ¼Ò¸¶¿î
def PayMoney(curPlayer, type_Price, price, costType=ChConfig.Def_Cost_Unknown, infoDict={}, quantity=1, costVIPGold= -1, isNotify=True, isMinus=False):
    if price == 0:
        return True
    if price < 0:
        GameWorld.Log('###---¿ÛÇ®Òì³£ = %s' % (price), curPlayer.GetPlayerID())
        return False
    lostMoney = price
    
    #20190917 »Ö¸´°óÓñ
#    if type_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
#        type_Price = IPY_GameWorld.TYPE_Price_Gold_Money #аæÎÞ°óÓñ£¬ÔÏȰóÓñÔÙÏÉÓñµÄ¿Û·¨¸Ä³É ¿ÛÏÉÓñ 2019/6/3
        
    #½ð×ÓÖ§¸¶
    if type_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
        curPlayerGold = GetMoneyReal(curPlayer, type_Price)
        if curPlayerGold < price and not isMinus:
            NotifyCode(curPlayer, "GoldErr")
            return False
        updPlayerGold = curPlayerGold - price
        SetMoney(curPlayer, type_Price, updPlayerGold)
        
        curBourseMoney = GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
        updBourseMoney = curBourseMoney
        #µ±Êǽ»Ò×Ëù¿Û·Ñ¡¢×êʯºì°üʱ£¬Ôò±Ø¶¨¿Û³ý½»Ò×¶î¶È
        if costType in ChConfig.UnUseInner_CostType:
            updBourseMoney = max(0, curBourseMoney - price)
        #ÆäËûÈç¹ûµ±Ç°½ð×ӱȽ»Ò×¶î¶È»¹ÉÙ£¬ÔòÇ¿ÖÆµ÷Õû½»Ò×¶î¶ÈΪµ±Ç°½ð×ÓÊý(ÕâÖÖÇé¿öÒ»°ãÊǷǽ»Ò×ËùÏû·ÑµÄ£¬ÐèҪͬ²½¿Û³ý½»Ò×Ëù¿É¹ºÂò¶î¶È)
        elif updPlayerGold < updBourseMoney:
            updBourseMoney = updPlayerGold
        updBourseMoney = max(0, updBourseMoney)
        if updBourseMoney != curBourseMoney:
            SetPlayerCurrency(curPlayer, ShareDefine.TYPE_Price_BourseMoney, updBourseMoney)
        infoDict["BourseMoney"] = updBourseMoney
        
    #½ðƱ֧¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
        curPlayerGoldPaper = GetMoneyReal(curPlayer, type_Price)
        if curPlayerGoldPaper < price and not isMinus:
            NotifyCode(curPlayer, "GoldPaperErr")
            return False
        updGoldPaper = curPlayerGoldPaper - price
        SetMoney(curPlayer, type_Price, updGoldPaper)
        
    #Òø×ÓÖ§¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Silver_Money:
        curPlayerSilver = GetSilver(curPlayer)
        if curPlayerSilver < price:
            NotifyCode(curPlayer, "SilverErr")
            return False
        #ÓÐ×ã¹»µÄǮ֧¸¶
        SetSilver(curPlayer, curPlayerSilver - price)
        
    #ÒøÆ±Ö§¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Silver_Paper:
        curPlayerSilverPaper = curPlayer.GetSilverPaper()
        if curPlayerSilverPaper < price:
            NotifyCode(curPlayer, "SilverPaperErr")
            return False
        #ÓÐ×ã¹»µÄǮ֧¸¶
        curPlayer.SetSilverPaper(curPlayerSilverPaper - price)
        
    #´ú±ÒÖ§¸¶
    elif type_Price == ShareDefine.TYPE_Price_PayCoin:
        curPlayerPayCoin = GetPayCoin(curPlayer)
        if curPlayerPayCoin < price:
            return False
        #ÓÐ×ã¹»µÄǮ֧¸¶
        SetPayCoin(curPlayer, curPlayerPayCoin - price)
        
    #×Ô¶¨Òå»õ±Ò
    elif type_Price in ShareDefine.TYPE_Price_CurrencyDict:
        curCurrency = GetPlayerCurrency(curPlayer, type_Price)
        if curCurrency < price:
            lostMoney = curCurrency
            lackPrice = price - curCurrency # »¹È±¶àÉÙÇ®
            tagMoneyInfo = GetEqualMoneyInfo(type_Price, lackPrice)
            if tagMoneyInfo:
                tagMoneyType, tagMoneyValue = tagMoneyInfo
                if not PayMoney(curPlayer, tagMoneyType, tagMoneyValue, costType, infoDict, quantity, costVIPGold, isNotify, isMinus):
                    #GameWorld.Log("µÈ¼Û»õ±ÒÒ²²»×ã")
                    return False
                GameWorld.Log("µÈ¼Û»õ±Ò²¹×ã¿Û³ý: type_Price%s, price=%s, curCurrency=%s, lackPrice=%s, tagMoneyType=%s, tagMoneyValue=%s" 
                                   % (type_Price, price, curCurrency, lackPrice, tagMoneyType, tagMoneyValue), curPlayer.GetPlayerID())
            else:
                #GameWorld.Log("ûÓеȼۻõ±Ò£¬ÎÞ·¨¿Û³ý")
                return False
        #ÓÐ×ã¹»µÄǮ֧¸¶
        SetPlayerCurrency(curPlayer, type_Price, curCurrency - lostMoney)
    else:
        GameWorld.Log("¸¶·Ñ½ðÇ®Òì³£ type_Price = %s" % (type_Price), curPlayer.GetPlayerID())
        return False
    
    #¸¶¿îÒÔºóºóÐø²Ù×÷
    __PayMoneyAfter(curPlayer, type_Price, lostMoney, costType, infoDict, quantity, costVIPGold)
    
    #֪ͨ¿Í»§¶Ëʧȥ½ðÇ®
    if isNotify:
        NotifyCode(curPlayer, "LostMoney", [type_Price, lostMoney])
    return True
## ¸¶¿îÒÔºóºóÐø²Ù×÷
#  @param curPlayer Íæ¼ÒʵÀý
#  @param type_Price ,»õ±ÒÀàÐÍ
#  @param price ,»õ±Ò¼Û¸ñ
#  @param costType ,Ïû·ÑÀàÐÍ
#  @param infoDict ,À©Õ¹ÐÅÏ¢
#  @param quantity Ïû·ÑÊýÁ¿
#  @return None
def __PayMoneyAfter(curPlayer, type_Price, price, costType, infoDict, quantity, costVIPGold):
    if type_Price in ShareDefine.UseTotalPriceTypeList:
        useTotal = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UseMoneyTotal % type_Price)
        useTotal = min(useTotal + price, ChConfig.Def_UpperLimit_DWord)
        NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UseMoneyTotal % type_Price, useTotal)
        NotifyUseMoneyTotal(curPlayer, [type_Price])
    
    #½ð×ÓÖ§¸¶
    if type_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
        __PayMoneyAfterByGoldMoney(curPlayer, type_Price, price, costType, infoDict, costVIPGold)
            
    #½ðƱ֧¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
        __PayMoneyAfterByGoldPaper(curPlayer, price, costType, infoDict)
    
    #Òø×ÓÖ§¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Silver_Money:
        __PayMoneyAfterBySilverMoney(curPlayer, price)
    
    #ÒøÆ±Ö§¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Silver_Paper:
        __PayMoneyAfterBySilverPaper(curPlayer, price)
    
    EventShell.EventRespons_OnMoneyChange(curPlayer, type_Price)
    
    #»îÔ¾¶È´¦Àí
    PlayerActivity.OnPayMoneyActivity(curPlayer, type_Price, price)
    #תÅ̻
    PlayerActTurntable.OnPlayerUseGold(curPlayer, type_Price, 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
    eventName = reason_name
    if costType in ChConfig.Def_CostType_Dict:
        eventName = ChConfig.Def_CostType_Dict[costType]
    #===========================================================================
    # isDivSonKey = False # ÊÇ·ñÇø·ÖÏû·Ñ¶ÔÏó
    # if costType in ChConfig.Def_CostType_Dict:
    #    eventName, reason_name, isDivSonKey = ChConfig.Def_CostType_Dict[costType]
    #    if costType in ChConfig.CostGroupToGoldShop:
    #        reason_name = ChConfig.Def_CostType_Dict[ChConfig.Def_Cost_BuyStoreItem][1]
    #    
    # if isDivSonKey and isinstance(infoDict, dict) and ChConfig.Def_Cost_Reason_SonKey in infoDict:
    #    reasonSon = infoDict[ChConfig.Def_Cost_Reason_SonKey]
    # else:
    #    reasonSon = reason_name
    # # ͳһ¸ñʽ: ¡¸Ïû·Ñ×é:Ïû·Ñ¶ÔÏó¡¹ ; ûÓÐÉèÖÃÏû·Ñ¶ÔÏóµÄĬÈÏΪÏû·Ñ×é
    # reason_name = "%s:%s" % (reason_name, reasonSon)
    #===========================================================================
    
    # ³ý×êʯ¼°°ó×êÍ⣬δָ¶¨²Ù×÷ÀàÐ͵IJ»¼Ç¼
    if type_Price not in [IPY_GameWorld.TYPE_Price_Gold_Money, IPY_GameWorld.TYPE_Price_Gold_Paper, ShareDefine.TYPE_Price_PayCoin] \
        and costType == ChConfig.Def_Cost_Unknown:
        #GameWorld.DebugLog("¸Ã»õ±ÒûÓÐÖ¸¶¨Ïû·ÑÀàÐͲ»¼Ç¼!type_Price=%s,costType=%s" % (type_Price, costType))
        return
    # Á÷ÏòÓà eventName
    #if eventName:
    DataRecordPack.DR_UseMoney(curPlayer, eventName, type_Price, price, infoDict) # Á÷Ïò
    EventReport.WriteEvent_virtual_resource(curPlayer, type_Price, reason_name, quantity,
                                            unitPrice, ShareDefine.Def_UserAction_Money_Use, infoDict)
    if type_Price == ShareDefine.TYPE_Price_PayCoin:
        playerID = curPlayer.GetPlayerID()
        nowMoney = GetMoneyReal(curPlayer, type_Price)
        orderInfo = infoDict.get("orderInfo", "")
        GameWorld.Log("¼Ç¼ÏûºÄ´ú±Ò: eventName=%s,price=%s,nowMoney=%s,orderInfo=%s" % (eventName, price, nowMoney, orderInfo), playerID)
        GameWorld.AddPlayerRec(playerID, ShareDefine.Def_PlayerRecType_PayCoin, [2, price, nowMoney], orderInfo, 1)
    #===========================================================================
    # if type_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
    #    EventReport.WriteEvent_virtual_cost(curPlayer, quantity, unitPrice, reason_name)
    # elif type_Price in [IPY_GameWorld.TYPE_Price_Gold_Paper, IPY_GameWorld.TYPE_Price_Silver_Money]:
    #    
    #    # ½ð±Òδָ¶¨Ïû·ÑÀàÐ͵IJ»¼Ç¼
    #    if type_Price == IPY_GameWorld.TYPE_Price_Silver_Money and costType == ChConfig.Def_Cost_Unknown:
    #        return
    #    EventReport.WriteEvent_virtual_resource(curPlayer, type_Price, reason_name, quantity, 
    #                                            unitPrice, ShareDefine.Def_UserAction_Money_Use)
    #    
    # # ×Ô¶¨Òå¼Ç¼
    # priceNameDict = {IPY_GameWorld.TYPE_Price_Gold_Money:["×êʯ", "GetGold", 0],
    #                 IPY_GameWorld.TYPE_Price_Gold_Paper:["°ó×ê", "GetGoldPaper", 0],
    #                 IPY_GameWorld.TYPE_Price_Silver_Money:["½ð±Ò", "GetSilver", ChConfig.Def_DRRecord_Min_Silver],
    #                 }
    # if type_Price in priceNameDict:
    #    typeName, moneyFuncName, minPrice = priceNameDict[type_Price]
    #    if minPrice <= 0 or price >= minPrice: 
    #        EventReport.WriteEvent_pay_money(curPlayer, reason_name, typeName, price, getattr(curPlayer, moneyFuncName)())
    #===========================================================================
    return
## ¸¶¿îÒÔºóºóÐø²Ù×÷(½ð×Ó)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param price ,»õ±Ò¼Û¸ñ
#  @return None
def __PayMoneyAfterByGoldMoney(curPlayer, type_Price, price, costType, infoDict, costVIPGold):
        
    
    # ³äÖµ»î¶¯Íæ¼ÒÏûºÄÔª±¦´¦Àí
    #PlayerGoldAction.PlayerUseGold(curPlayer, price)
    
    # Ïû·Ñ·µÀû
    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())
        
    # ʼþ»ã±¨
    #===========================================================================
    # if costType == ChConfig.Def_Cost_BourseBuy:
    #    # ½»Ò×Ëù¹ºÂòÎïÆ·£¬»ã±¨½»Ò××êʯ
    #    playerName = curPlayer.GetPlayerName()
    #    leftGold = curPlayer.GetGold()
    #    eventParam = "RoleID=%s,Price=%s,TradeType=Lost,LeftGold=%s" \
    #                    % (playerName, price, leftGold)
    #    EventReport.EventReport(ShareDefine.Def_UserAction_TradeGold, eventParam, curPlayer)
    # else:
    #    playerName = curPlayer.GetPlayerName()
    #    leftGold = curPlayer.GetGold()
    #    eventParam = "RoleID=%s,CostType=%s,ItemID=%s,Price=%s,LeftGold=%s" \
    #                    % (playerName, costType, infoDict, price, leftGold)
    #    EventReport.EventReport(ShareDefine.Def_UserAction_UseGold, eventParam, curPlayer)
    #===========================================================================
    
    # ֪ͨԪ±¦Ïû·Ñ¼Ç¼
    #__Sync_GoldCostReport(curPlayer, costType, price, expandValue)
    return
## ֪ͨԪ±¦Ïû·Ñ¼Ç¼
#  @param curPlayer: Íæ¼ÒʵÀý
#  @param costType: Ïû·ÑµãÀàÐÍ
#  @param price: Ïû·Ñ¶î¶È
#  @param itemID: ÎïÆ·id£¬Ïû·ÑÀàÐÍΪÎïÆ·Ê±¿ÉÌî
#  @return None
def __Sync_GoldCostReport(curPlayer, costType, price, itemID=0):
    sendPack = ChPyNetSendPack.tagMCGoldCostReport()
    sendPack.Clear()
    sendPack.CostType = costType
    sendPack.Price = price
    sendPack.ItemID = itemID
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
## ¸¶¿îÒÔºóºóÐø²Ù×÷(½ðƱ)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param price ,»õ±Ò¼Û¸ñ
#  @return None
def __PayMoneyAfterByGoldPaper(curPlayer, price, costType, infoDict):    
    
    # ʼþ»ã±¨
    #===========================================================================
    # playerName = curPlayer.GetPlayerName()
    # leftGoldPaper = curPlayer.GetGoldPaper()
    # eventParam = "RoleID=%s,CostType=%s,ItemID=%s,Price=%s,LeftGoldPaper=%s" \
    #                % (playerName, costType, infoDict, price, leftGoldPaper)
    # EventReport.EventReport(ShareDefine.Def_UserAction_UseGoldPaper, eventParam, curPlayer)
    #===========================================================================
    return
## ¸¶¿îÒÔºóºóÐø²Ù×÷(½ðƱ)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param price ,»õ±Ò¼Û¸ñ
#  @return None
def __PayMoneyAfterBySilverMoney(curPlayer, price):    
    return
## ¸¶¿îÒÔºóºóÐø²Ù×÷(½ðƱ)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param price ,»õ±Ò¼Û¸ñ
#  @return None
def __PayMoneyAfterBySilverPaper(curPlayer, price):    
    return
#---------------------------------------------------------------------
##Íæ¼Ò»ñµÃ½ðÇ®
# @param curPlayer Íæ¼ÒʵÀý
# @param value ,»õ±Ò¼Û¸ñ
# @param priceType ,»õ±ÒÀàÐÍ
# @return ·µ»ØÖµÕæ, ¸øÇ®³É¹¦
# @param isSysHint ÊÇ·ñϵͳÌáʾ£¨Ä¬ÈÏÊÇ£©
# @remarks Íæ¼Ò»ñµÃ½ðÇ®
def GiveMoney(curPlayer, priceType, value, giveType=ChConfig.Def_GiveMoney_Unknown, addDataDict={}, isSysHint=True, isGiveBourseMoney=True):
    if value == 0:
        return True
    
    if value < 0:
        GameWorld.Log('Íæ¼Ò»ñµÃ½ðÇ®Òì³£ £¬ value = %s , priceType = %s ,' % (value, priceType))
        return
    
    if GameWorld.IsCrossServer():
        serverGroupID = GetPlayerServerGroupID(curPlayer)
        msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "MoneyType":priceType, "Value":value, "GiveType":giveType, "AddDataDict":addDataDict}
        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_GiveMoney, msgInfo, [serverGroupID])
        return True
        
    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
        updPlayerGold = GetMoneyReal(curPlayer, priceType) + value
        if updPlayerGold > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return
        SetMoney(curPlayer, priceType, updPlayerGold)
        
        if isGiveBourseMoney and updPlayerGold > 0:
            GiveMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney, min(value, updPlayerGold))
        addDataDict["BourseMoney"] = GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
        
    elif priceType == IPY_GameWorld.TYPE_Price_Gold_Paper:
        updPlayerGoldPaper = GetMoneyReal(curPlayer, priceType)  + value
        if updPlayerGoldPaper > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return
        SetMoney(curPlayer, priceType, updPlayerGoldPaper)
        
    elif priceType == IPY_GameWorld.TYPE_Price_Silver_Money:
        # ½ðǮ֧³Ö³¬¹ý20ÒÚ, Ôݲ»×öÉÏÏÞ¿ØÖÆ
#        if curSilver + value > ChConfig.Def_PlayerTotalMoney_Silver:
#            #³¬¹ý½ðÇ®ÉÏÏÞ
#            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
#            return
        SetSilver(curPlayer, GetSilver(curPlayer) + value)
       
        
    elif priceType == IPY_GameWorld.TYPE_Price_Silver_Paper:
        if curPlayer.GetSilverPaper() + value > ChConfig.Def_PlayerTotalMoney_Silver:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return
        
        curPlayer.SetSilverPaper(curPlayer.GetSilverPaper() + value)
        
    elif priceType == ShareDefine.TYPE_Price_PayCoin:
        SetPayCoin(curPlayer, GetPayCoin(curPlayer) + value)
        
    #×Ô¶¨Òå»õ±Ò
    elif priceType in ShareDefine.TYPE_Price_CurrencyDict:
        curCurrency = GetPlayerCurrency(curPlayer, priceType)
        if curCurrency >= ChConfig.Def_UpperLimit_DWord:
            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)
            EventShell.EventRespons_GetRealmPoint(curPlayer)
    else:
        GameWorld.ErrLog("½ðÇ®ÀàÐÍ´íÎó, priceType=%s,value=%s,giveType=%s" % (priceType, value, giveType), curPlayer.GetPlayerID())
        DataRecordPack.DR_GiveMoneyError(curPlayer, priceType, value, giveType, addDataDict)
        return
    
    if isSysHint and priceType != ShareDefine.TYPE_Price_BourseMoney:
        #֪ͨ¿Í»§¶ËµÃµ½½ðÇ®
        NotifyCode(curPlayer, "GetMoney", [priceType, value])
        
    __GiveMoneyAfter(curPlayer, priceType, value, giveType, addDataDict)
    
    return True
def __GiveMoneyAfter(curPlayer, priceType, value, giveType, addDataDict):
    # ³ý×êʯ¼°°ó×êÍ⣬δָ¶¨²Ù×÷ÀàÐ͵IJ»¼Ç¼
    
    EventShell.EventRespons_OnMoneyChange(curPlayer, priceType)
    
    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))
        return
    eventName = giveType
    if giveType in ChConfig.Def_GetType_Dict:
        eventName = ChConfig.Def_GetType_Dict[giveType]
        addDataDict["eventName"] = eventName
        
    DataRecordPack.DR_GiveMoney(curPlayer, eventName, priceType, value, addDataDict)
    EventReport.WriteEvent_virtual_resource(curPlayer, priceType, giveType, 1, value,
                                            ShareDefine.Def_UserAction_Money_Get, addDataDict)
    
    if priceType == ShareDefine.TYPE_Price_PayCoin:
        playerID = curPlayer.GetPlayerID()
        nowMoney = GetMoneyReal(curPlayer, priceType)
        orderInfo = addDataDict.get("orderInfo", "")
        GameWorld.Log("¼Ç¼»ñµÃ´ú±Ò: eventName=%s,value=%s,nowMoney=%s,orderInfo=%s" % (eventName, value, nowMoney, orderInfo), playerID)
        GameWorld.AddPlayerRec(playerID, ShareDefine.Def_PlayerRecType_PayCoin, [1, value, nowMoney], orderInfo, 1)
#===============================================================================
#    reason_name = "Unknown" if not giveType else giveType
#    eventName = reason_name
#    if giveType in ChConfig.Def_GetType_Dict:
#        eventName, reason_name = ChConfig.Def_GetType_Dict[giveType][:2]
#    if isinstance(addDataDict, dict) and ChConfig.Def_Give_Reason_SonKey in addDataDict:
#        reasonSon = addDataDict[ChConfig.Def_Give_Reason_SonKey]
#    else:
#        reasonSon = reason_name
#    # ͳһ¸ñʽ: ¡¸»ñµÃ×é:»ñµÃÔÒò¡¹
#    reason_name = "%s:%s" % (reason_name, reasonSon)
#            
#    # Á÷ÏòÓà eventName
#    if eventName:
#        DataRecordPack.DR_GiveMoney(curPlayer, eventName, priceType, value, addDataDict)
#        
#    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
#        playerName = curPlayer.GetPlayerName()
#        eventParam = "RoleID=%s,AddGold=%s,LeftGold=%s,AddDataDict=%s" \
#                    % (playerName, value, curPlayer.GetGold(), addDataDict)
#        EventReport.EventReport(ShareDefine.Def_UserAction_GameMakeGold, eventParam, curPlayer)
#        
#    elif priceType == IPY_GameWorld.TYPE_Price_Gold_Paper:
#        playerName = curPlayer.GetPlayerName()
#        eventParam = "RoleID=%s,AddGoldPaper=%s,LeftGoldPaper=%s,AddDataDict=%s" \
#                        % (playerName, value, curPlayer.GetGoldPaper(), addDataDict)
#        EventReport.EventReport(ShareDefine.Def_UserAction_GameMakeGoldPaper, eventParam, curPlayer)
#    
# 
#    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money: #and eventName != "CoinToGold":
#        EventReport.WriteEvent_virtual_reward(curPlayer, value, reason_name)
#    # ¶þ¼¶»õ±Ò²ú³ö¼Ç¼, ÔÝÖ»¼Ç¼°ó×ê¡¢½ð±Ò
#    elif priceType in [IPY_GameWorld.TYPE_Price_Gold_Paper, IPY_GameWorld.TYPE_Price_Silver_Money]:
#        EventReport.WriteEvent_virtual_resource(curPlayer, priceType, reason_name, 1, value,
#                                                ShareDefine.Def_UserAction_Money_Get)
#        
#    # ×Ô¶¨Òå¼Ç¼
#    priceNameDict = {IPY_GameWorld.TYPE_Price_Gold_Money:["×êʯ", "GetGold", 0],
#                     IPY_GameWorld.TYPE_Price_Gold_Paper:["°ó×ê", "GetGoldPaper", 0],
#                     IPY_GameWorld.TYPE_Price_Silver_Money:["½ð±Ò", "GetSilver", ChConfig.Def_DRRecord_Min_Silver],
#                     }
#    if priceType in priceNameDict:
#        typeName, moneyFuncName, minPrice = priceNameDict[priceType]
#        if minPrice <= 0 or value >= minPrice: 
#            EventReport.WriteEvent_give_money(curPlayer, reason_name, typeName, value, getattr(curPlayer, moneyFuncName)())
#===============================================================================
        
    return
#---------------------------------------------------------------------
##Íæ¼ÒÄÜ·ñ»ñµÃ½ðÇ®
# @param curPlayer Íæ¼ÒʵÀý
# @param value ,»õ±Ò¼Û¸ñ
# @param type ,»õ±ÒÀàÐÍ
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks Íæ¼ÒÄÜ·ñ»ñµÃ½ðÇ®
def CanGiveMoney(curPlayer, priceType, value):
    if value == 0:
        return True
    
    if priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
        if curPlayer.GetGold() + value > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return False 
    elif priceType == IPY_GameWorld.TYPE_Price_Gold_Paper:
        if curPlayer.GetGoldPaper() + value > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return False
    elif priceType == IPY_GameWorld.TYPE_Price_Silver_Money:
        #½ð±ÒÖ§³Ö³¬¹ý20ÒÚ£¬Ôݲ»×öÉÏÏÞ¿ØÖÆ
        pass
#        if GetSilver(curPlayer) + value > ChConfig.Def_PlayerTotalMoney_Silver:
#            #³¬¹ý½ðÇ®ÉÏÏÞ
#            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
#            return False
    elif priceType == IPY_GameWorld.TYPE_Price_Silver_Paper:
        if curPlayer.GetSilverPaper() + value > ChConfig.Def_PlayerTotalMoney_Silver:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return False
    elif priceType == ShareDefine.TYPE_Price_PayCoin:
        pass
    elif priceType in ShareDefine.TYPE_Price_CurrencyDict:
        curCurrency = GetPlayerCurrency(curPlayer, priceType)
        if curCurrency + value > ChConfig.Def_UpperLimit_DWord:
            return False
    else:
        
        GameWorld.Log("½ðÇ®ÀàÐÍ = %sÌî´íÀ²" % (priceType), curPlayer.GetPlayerID())
        return False 
    
    return True
#---------------------------------------------------------------------
##Íæ¼Ò×Ô¶¯»ØÑª
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò×Ô¶¯»ØÑª
def PlayerAutoRestoreHP(curPlayer, tick):
    return
    
#---------------------------------------------------------------------
##Íæ¼Ò×Ô¶¯»ØÄ§
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼Ò×Ô¶¯»ØÄ§
def PlayerAutoRestoreMP(curPlayer, tick):
    return
##»ñµÃµ±Ç°Íæ¼ÒµÄ²Î¿¼¾Ñé
# @param curPlayer Íæ¼ÒʵÀý
# @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
#---------------------------------------------------------------------
##Ôö¼ÓÍæ¼ÒµÄPKÖµ
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ôö¼ÓÍæ¼ÒµÄPKÖµ
def AddPlayerPKValue(curPlayer, tick):
    curPlayerPKValue = curPlayer.GetPKValue()
    maxPKValue = GetMaxPKValue()
    if curPlayerPKValue >= maxPKValue:
        #µ±Ç°PKÖµÒѵ½ÉÏÏÞ,²»Ìí¼Ó
        return
    
    #Ìí¼ÓµãÊý
    addPoint = 1
    changePKValue = ChangePKValue(curPlayer, addPoint, tick)
    
    if changePKValue >= maxPKValue:
        #PK_wll_0: ÄúɱÄõ¹ýÖØ£¬ÔÚºìÃû״̬ÏûʧǰÄú½«²»ÄܼÌÐø¶øÒѹ¥»÷ËûÈË
        NotifyCode(curPlayer, "PK_lhs_202580")
        
    #Íæ¼ÒïÚ³µÉíÉϼÇÂ¼Íæ¼ÒÃû×ÖÑÕÉ«ÐÅÏ¢(±ØÐëÔÚÉèÖúìÃûÒÔºó)
    #PlayerTruck.ChangeTruckNoteInfo(curPlayer)
    return
def ChangePKValue(curPlayer, addValue, tick):
    '''¸ü¸ÄPKÖµ'''
    curPlayerPKValue = curPlayer.GetPKValue()
    maxPKValue = GetMaxPKValue()
    newPKValue = max(0, min(maxPKValue, curPlayerPKValue + addValue))
    if newPKValue == curPlayerPKValue:
        return newPKValue
    
    GameWorld.DebugLog("¸üÐÂPKÖµ: curPlayerPKValue=%s,newPKValue=%s,addValue=%s" % (curPlayerPKValue, newPKValue, addValue), curPlayer.GetPlayerID())
    if newPKValue == 0:
        ClearPKValue(curPlayer)
    else:
        addBuffID = ChConfig.Def_SkillID_Red
        curPlayer.SetPKValue(newPKValue)
        findBuffInfo = SkillCommon.FindBuffByID(curPlayer, addBuffID)
        redBuff = findBuffInfo[0]
        addTimeValue = newPKValue - curPlayerPKValue
        if not redBuff:
            SkillCommon.AddBuffBySkillType_NoRefurbish(curPlayer, addBuffID, tick)
            if newPKValue > 1:
                findBuffInfo = SkillCommon.FindBuffByID(curPlayer, addBuffID)
                redBuff = findBuffInfo[0]
                addTimeValue = newPKValue - 1
                
        if addTimeValue and redBuff:
            __AddPKValueRedBuffTime(curPlayer, redBuff, addTimeValue)
    return newPKValue
def __AddPKValueRedBuffTime(curPlayer, redBuff, addTimeValue):
    '''Ôö¼ÓPKÖµ¶ÔÓ¦buffʱ³¤
    @param addTimeValue: Ôö¼ÓµÄbuffµ¥Î»Ê±³¤´ÎÊý, Ö§³ÖÕý¸º
    '''
    buffSkill = redBuff.GetSkill()
    if not buffSkill:
        return
    buffType = SkillCommon.GetBuffType(buffSkill)
    addTime = buffSkill.GetLastTime() * addTimeValue # ÓÐÕý¸º
    remainTime = redBuff.GetRemainTime()
    resultTime = min(max(0, remainTime + addTime), ChConfig.Def_Max_Buff_RemainTime)
    redBuff.SetRemainTime(resultTime)
    BuffSkill.PYSync_RefreshBuff(curPlayer, redBuff, buffType)
    GameWorld.DebugLog("    Ôö¼ÓºìÃûbuffʱ³¤: addTimeValue=%s,remainTime=%s,addTime=%s,resultTime=%s" 
                       % (addTimeValue, remainTime, addTime, resultTime), curPlayer.GetPlayerID())
    return
def RefreshPKValueByRedBuff(curPlayer):
    ## ˢкìÃû¶ÔÓ¦PKValue
    curPKValue = curPlayer.GetPKValue()
    if not curPKValue:
        return
    if PlayerTJG.GetIsTJG(curPlayer):
        return
    redBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_Red)[0]
    if not redBuff:
        curPlayer.SetPKValue(0)
        return
    buffSkill = redBuff.GetSkill()
    if not buffSkill:
        return
    remainTime = redBuff.GetRemainTime()
    perPKValueTime = buffSkill.GetLastTime()
    pkValue = int(math.ceil(remainTime / float(perPKValueTime)))
    if curPKValue != pkValue:
        curPlayer.SetPKValue(pkValue)
        GameWorld.DebugLog("¸üÐÂÍæ¼ÒPKÖµ: remainTime=%s,pkValue=%s" % (remainTime, pkValue), curPlayer.GetPlayerID())
    return
def ClearPKValue(curPlayer):
    '''Çå³ýPKÖµ'''
    curPlayer.SetPKValue(0)
    tick = GameWorld.GetGameWorld().GetTick()
    BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_Red, tick)
    return
def GetMaxPKValue():
    '''»ñÈ¡×î´óPKÖµ'''
    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):
    # ³ÆºÅ¶îÍâÔö¼ÓÍæ¼Òÿ¼¶»ñµÃµÄÁé¸ùµã
    titleID = IpyGameDataPY.GetFuncCfg("TitleAddPoint")
    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
    
#---------------------------------------------------------------------
## ¹¦ÄÜÄ£¿éÕ½¶·Á¦Àà
#
#  ·ÖÄ£¿é¼ÆËãÕ½¶·Á¦
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_AtkBackHP) # ¹¥»÷»Ø¸´ÑªÁ¿
        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()
        
        #»ñÈ¡²ß»®ÅäÖõıí¸ñ
        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
        return totalFightPower
    
    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
###############################################################
#ÈËÎï¿ØÖÆÀà
## ÈËÎï¿ØÖÆÀà
#
#  ÈËÎïËÀÍöµÈÂß¼´¦Àí
class PlayerControl:
    __Player = None
    __fpTypeObjDict = {}
    #---------------------------------------------------------------------
    ## ³õʼ»¯
    #  @param self ÀàʵÀý
    #  @param iPlayer Íæ¼ÒʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @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¼¶ºó ÒÔǰÊǼӼ¼ÄܵãÏָijÉÖ±½ÓÉý¼¶ºó¶Á±í¼Ó¼¼ÄÜ
    #  @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 ÀàʵÀý
    #  @param curPlayer Íæ¼ÒʵÀý
    #  @param curLV µ±Ç°µÈ¼¶
    #  @return ·µ»ØÖµÕæ, ÐèÒª
    #  @remarks ¼ì²éÍæ¼ÒÊÇ·ñÐèÒª·â¾ô
    def __LVUpDoInvestiture(self, curPlayer, curLV):
#===============================================================================
#        ´ËÂß¼²»ÄÜÓà GetTotalExp, 
#        ¸Ä¶¯ÇëÉ÷ÖØ!
#===============================================================================
        #1. ¼ì²éÍæ¼ÒÊÇ·ñÔÚ·â¾ôµÈ¼¶
        if curLV < 20 or curLV % 10 != 0:
            return False
        
        curMission = curPlayer.FindMission(curLV * 100)
        if curMission != None and curMission.GetState() == ChConfig.Def_Mission_State_Over:
            #ÈÎÎñÍê³É
            return False
            
        if curMission == None:
            #2. Èç¹ûÔÚ·â¾ôµÈ¼¶, ²¢ÇÒ¼´½«Éýµ½ÏÂÒ»¼¶, ´¥·¢·â¾ôÈÎÎñ
            if EventShell.EventResponse_LVFull(curPlayer) != True:
                GameWorld.Log("´¥·¢·â¾ôÈÎÎñʧ°Ü", curPlayer.GetPlayerID())
                return False
            
        return True
    
    #---------------------------------------------------------------------
    
    ## ¼Ó¾ÑéÖµ 
    #  @param self ÀàʵÀý
    #  @param addExp Ìí¼ÓµÄ¾Ñé
    #  @param exp_rate ¾Ñé±¶ÂÊ
    #  @param expViewType ¾Ñé»ñµÃµÄÇþµÀ
    #  @param isSysHint ÊÇ·ñϵͳÌáʾ£¨Ä¬ÈÏÊÇ£©
    #  @return ²¼¶ûÖµ
    def AddExp(self, addExp, expViewType=ShareDefine.Def_ViewExpType_Mission, isSysHint=True, addSkillID=0, expRateEx=0):
        curPlayer = self.__Player
        finalAddExp, expNotifyType = self.__AddExp(curPlayer, addExp, expViewType, isSysHint, addSkillID, expRateEx)
        
        # ֪ͨ¿Í»§¶Ë¾ÑéÀ´Ô´
        if finalAddExp:
            sendPack = ChPyNetSendPack.tagMCAddExp()
            sendPack.ExpPoint = finalAddExp / ChConfig.Def_PerPointValue
            sendPack.Exp = finalAddExp % ChConfig.Def_PerPointValue
            sendPack.Source = expNotifyType # ¿Í»§¶ËչʾÓÃ
            NetPackCommon.SendFakePack(curPlayer, sendPack)
            
        #¸±±¾»ñµÃ¾Ñé, ÎÞÂÛ»ñµÃ¶àÉÙ¾Ñé¾ùÐè֪ͨ, ÓÐЩ¸±±¾Âß¼ÐèҪͨ¹ý»ñµÃ¾Ñéʱ»ú´¦Àí
        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:
            # ²»½øÈë¼ÆËã
            return addExp, expViewType
        
        #È¡µÃÈËÎﵱǰ¾Ñé
        #curTotalExp = GetPlayerTotalExp(curPlayer)
        curTotalExp = curPlayer.GetExpPoint() * ChConfig.Def_PerPointValue + curPlayer.GetTotalExp()
        maxLV = GetPlayerMaxLV(curPlayer)
        maxLVExpStore = IpyGameDataPY.GetFuncCfg("MaxLVExpStore", 1)
        
        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
        # ¼ì²é×î´óµÈ¼¶
        if curLV >= maxLV and curTotalExp >= maxLVExpStore:
            self.__NotifyExpFull(curPlayer, "GeRen_admin_825676")
            #GameWorld.DebugLog("¾ÑéÒÑÂú£¡ÒÑÂú¼¶£¡curLV=%s" % (curLV), curPlayer.GetPlayerID())
            return 0, expViewType
        
        # ɱ¹Ö
        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
                
        elif expViewType in [ShareDefine.Def_ViewExpType_GameEvent, ShareDefine.Def_ViewExpType_Sit]:
            exp_rate = curPlayer.GetGameEventExpRate()
            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:
            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
        
        if curPlayer.GetExpPoint() != expPoint:
            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
    
    ## ¾ÑéÂúÌáʾ
    def __NotifyExpFull(self, curPlayer, expFullNotifyMark):
        expFullNotifyState = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ExpFullNotify)
        if not expFullNotifyState:
            NotifyCode(curPlayer, expFullNotifyMark)
            curPlayer.SetDict(ChConfig.Def_PlayerKey_ExpFullNotify, 1)
        return
    
    ## ÈËÎïÉý¼¶ »ØÂúѪ »ØÂúħ£¬´¥·¢Ìí¼Ó¼¼ÄÜ£¬ÈÎÎñ£¬¼ÓÊôÐԵ㣨ÔÀ´²¿·Öº¯Êý²Ù×÷·ÅÔÚ¼Ó¾ÑéÖÐ ÏÖÔÚÌá³öÀ´£©
    #  @param handLvUp: ÊÇ·ñÊÇÊÖ¶¯Éý¼¶
    #  @return: None
    #  @remarks: Èç¹ûÊÇ×Ô¶¯Éý¼¶²»¸ø²ÎÊý ¶øÈç¹ûÊÇÊÖ¶¯Éý¼¶ÐèÒª¸ø²ÎÊý ÊÇÊÖ¶¯Éý¼¶ True 
    #  1-20¼¶×Ô¶¯Éý¼¶Ö±½Ó¼Óµã Ö®ºó±ØÐëÊÖ¶¯Éý¼¶ ¸ø×ÔÓÉÊôÐÔµã
    def PlayerLvUp(self, handLvUp=False):
        curPlayer = self.__Player
        
        if GameObj.GetHP(curPlayer) <= 0:
            #Íæ¼ÒËÀÍö²»¿ÉÉý¼¶
            return
        
        #lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
        lvIpyData = IpyGameDataPY.GetIpyGameData("PlayerLV", curPlayer.GetLV())
        if not lvIpyData:
            GameWorld.ErrLog("¾Ñé±íÒì³£  lv= %s" % curPlayer.GetLV())
            return
        
        #lvUpNeedExp = GetLVUPTotalExpNeed(lvIpyData)
        lvUpNeedExp = lvIpyData.GetExpPoint() * ChConfig.Def_PerPointValue + lvIpyData.GetExp()
        
        if lvUpNeedExp <= 0:
            return
        
        #Ôö¼Ó¾Ñé
        #curTotalExp = GetPlayerTotalExp(curPlayer)
        curTotalExp = curPlayer.GetExpPoint() * ChConfig.Def_PerPointValue + curPlayer.GetTotalExp()
        #δ´ïµ½Éý¼¶¾Ñé
        if curTotalExp < lvUpNeedExp:
            return
        needSyncTalentPoint = False
        playerNeedDoLVUp = False
        curLV = curPlayer.GetLV()
        maxLV = GetPlayerMaxLV(curPlayer)
        
        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)
        
        while curTotalExp >= lvUpNeedExp and curLV < maxLV:
            
            playerNeedDoLVUp = True
            
            #---ÈËÎïÉý¼¶³É¹¦---
            curLV = curLV + 1
            
            isNotifyServer = True
            if curLV < 50:
                # ¼õÉÙǰÆÚµÄ¹ã²¥£¬³ÌÐò¿ØÖÆ
                isNotifyServer = False
            
            curPlayer.SetLV(curLV, isNotifyServer)
            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.__DoLvUpAddSkill()  # Éý¼¶¼Ó¼¼ÄÜ
            
            lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
            # ´óʦÌ츳µã
            if lvIpyData:
                addTalentPoint = lvIpyData.GetTalentPoint()
                if addTalentPoint:
                    needSyncTalentPoint = True
                    PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, addTalentPoint)
            
            EventShell.EventResponse_LVUp(curPlayer)  # Éý¼¶´¥·¢Ê¼þ
            
            PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_LVUp, 1)
            #---ÊÇ·ñ¼ÌÐøÑ»·---
            curTotalExp = curTotalExp - lvUpNeedExp
            
            #»ñµÃÏÂÒ»¼¶µÄ¾Ñé±í
            lvUpNeedExp = GetLVUPTotalExpNeed(lvIpyData)
            
            if lvUpNeedExp <= 0:
                break
            
        curPlayer.EndRefreshState() # ½áÊøË¢Ðºó£¬Óбä¸üµÄÊôÐÔҪ֪ͨ¿Í»§¶ËµÄÐèÖØÐÂÉèÖÃÒ»´Î
        #---------------------------------------------------
        #ÓÐÉý¼¶, תÉúʱ¸ÕºÃÊÇתÉúµÈ¼¶»áĬÈÏ+1¼¶
        if playerNeedDoLVUp:
            aftLV = curPlayer.GetLV()
            aftFreePoint = curPlayer.GetFreePoint()
            aftBaseSTR = curPlayer.GetBaseSTR()
            aftBasePNE = curPlayer.GetBasePNE()
            aftBasePHY = curPlayer.GetBasePHY()
            aftBaseCON = curPlayer.GetBaseCON()
            if aftLV > befLV:
                curPlayer.SetLV(aftLV, False) # ÕâÀï²»ÔÙ֪ͨGameServer
                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)
            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)
            #½«ÑªÉèÖÃΪ×î´ó
            GameObj.SetHPFull(curPlayer)
            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
    
    def __GiveLVMailAward(self, curLV):
        # ¸øµÈ¼¶Óʼþ½±Àø
        mailLVAwardDict = IpyGameDataPY.GetFuncEvalCfg("MailLVAward", 1, {})
        if curLV not in mailLVAwardDict:
            return
        mailTypeKey, mailItemList = mailLVAwardDict[curLV]
        curPlayer = self.__Player
        SendMailByKey(mailTypeKey, [curPlayer.GetPlayerID()], mailItemList, [curLV])
        return
    
    #---------------------------------------------------------------------
    def CalcRoleBaseAttr(self, curPlayer):
        # ¼ÆËãÍæ¼Ò½ÇÉ«»ù´¡ÊôÐÔÖµ
        
        #curPlayerID = curPlayer.GetID()
        job = curPlayer.GetJob()
        roleType = curPlayer.GetRoleType()
        ipyData = IpyGameDataPY.GetIpyGameData("CreateRole", roleType)
        if not ipyData:
            return
        baseAttrIDList = ipyData.GetBaseAttrIDList()
        baseAttrValueList = ipyData.GetBaseAttrValueList()
        allAttrList = [{} for _ in range(4)]
        
        # ³õʼÊôÐÔ
        if baseAttrIDList and baseAttrValueList and len(baseAttrIDList) == len(baseAttrValueList):
            for i, attrID in enumerate(baseAttrIDList):
                CalcAttrDict_Type(attrID, baseAttrValueList[i], allAttrList)
        #GameWorld.DebugLog("³õʼ¼ÓÊôÐÔ: %s" % allAttrList)
        
        # µÈ¼¶³É³¤ÊôÐÔ
        LV = curPlayer.GetLV()
        lvAttrDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAttr%s" % job, 1)
        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))
            if hadRefreshAttr and befPQLV < curPQLV:
                for pqlv in xrange(befPQLV+1, curPQLV+1):
                    EventShell.EventRespons_LingGenQualityUP(curPlayer, pointAttrID, pqlv)
                
        #GameWorld.DebugLog("µÈ¼¶ÊôÐÔµã¼ÓÊôÐÔ: %s" % allAttrList)
        #GameWorld.DebugLog("Áé¸ùÆ·½×µÈ¼¶ÊôÐÔ: %s" % lingGenQualityAttrList)
        #GameWorld.DebugLog("Áé¸ùµãÊý¸½¼ÓÕ½Á¦: %s" % pointFightPowerEx)
        curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % 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)
        
        #ÔÚ´Ë´¦°ÑËùÓÐÊôÐԵIJ»Í¬Í¨Öª¸ø¿Í»§¶Ë
        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 ÀàʵÀý
    #  @param isForce ÊÇ·ñÇ¿ÖÆË¢ÐÂ
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Ë¢ÐÂÍæ¼ÒËùÓÐ״̬
    def RefreshAllState(self, isSyncBuff=False, billboardFunc=None, isForce=False):
        GameWorld.DebugLog("Start RefreshAllState!!!")
        
        self.RefreshPlayerActionState()
        self.RefreshPlayerAttrState(billboardFunc, isForce)
        return
    
    
    ## ÖØ¼ÆË㲢ˢÐÂÍæ¼ÒËùÓÐ״̬, ĿǰֻÓÃÓëÇл»µØÍ¼
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Ë¢ÐÂÍæ¼ÒËùÓÐ״̬
    def ReCalcAllState(self):
        GameWorld.DebugLog("Start ReCalcAllState!!!")
        curPlayer = self.__Player
        
        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)
        self.RefreshAllState(isForce=True)
        GameWorld.DebugLog("End ReCalcAllState!!!")
        return
    
    
    # BUFF²ãµ¥¶ÀË¢ÐÂÊôÐÔ£¬¹¦ÄÜÊôÐÔÈ¡»º´æ---------------------------------------------
    def RefreshPlayerAttrByBuff(self, isForce=False):
        curPlayer = self.__Player
        curPlayer.SetDict(ChConfig.Def_Player_RefreshAttrByBuff, 1)
        
        if isForce:
            self.RefreshPlayerAttrByBuffEx()
        return True
    
    # BUFF²ãµ¥¶ÀË¢ÐÂÊôÐÔ
    def RefreshPlayerAttrByBuffEx(self):
        
        curPlayer = self.__Player
        if curPlayer.GetDictByKey(ChConfig.Def_Player_RefreshAttrByBuff) != 1:
            return
        
        GameWorld.DebugLog("Start RefreshPlayerAttrByBuffEx!!!")
        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)
        #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!!!")
        return
    
    
    #===========================================================================
    # #×°±¸ºÍBUFF Ч¹ûµÄ¼ÆËãÒÆµ½Íâ²ã
    # #RefreshPlayerBuffOnAttrAddEffect
    # #RefreshPlayerEquipAttribute(curPlayer)
    #===========================================================================
    ## Ë¢ÐÂÍæ¼ÒÊôÐÔµ÷Óô˺¯Êý£¬Á¢¼´Ë¢Ð¸ÄΪ֪ͨˢУ¬ÓÉProcessStatueͳһˢÐÂÒ»´Î
    ## ÅÅÐаñÀàµÄË¢ÐÂisForceÐèҪΪTrue
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    def RefreshPlayerAttrState(self, billboardFunc=None, isForce=False):
        curPlayer = self.__Player
        curPlayer.SetDict(ChConfig.Def_Player_RefreshAttr, 1)
            
        if billboardFunc and billboardFunc not in PyGameData.g_refreshAttrBillboardFunc:
            PyGameData.g_refreshAttrBillboardFunc.append(billboardFunc)
            
        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):
        ''' ±¾ÏîĿˢÊôÐÔ¹æÔò
                    ÊôÐÔ£º
            1.¹Ì¶¨ÊôÐÔ£ºÈç¹¥»÷+100
            2.°Ù·Ö±ÈÊôÐÔ£º Èç¹¥»÷+5%£¬°Ù·Ö±È¼Ó³É»ùÖµ½öΪ¹Ì¶¨ÊôÐÔ£¬°Ù·Ö±È¼Ó³ÉÊôÐÔÖµ²»±»³ýbuff°Ù·Ö±ÈÍâµÄÈκΰٷֱÈÊôÐÔ¶þ´Î¼Ó³É
            
                    ²ã¼¶£º
            1.ÊôÐԲ㼶£ºËùÓй¦ÄÜͬһ²ã¼¶
            2.buff²ã¼¶£º°Ù·Ö±È¿É¶Ô¹¦ÄܰٷֱȼӳɵÄÊôÐÔ½øÐжþ´Î¼Ó³É
            
                    ¹¦ÄÜÄ£¿é£º¶¨ÒåÒ»¸ö¹¦ÄÜ£¬±ÈÈçÁé¸ùÄ£¿é£¬Ò»¸öÄ£¿é¿ÉÄܰüº¬¶à¸ö¹¦Äܵã
                    ¹¦Äܵ㣺ij¸öÄ£¿éϵĸ÷¸öÊôÐÔ¹¦Äܵ㣬ÈçÁé¸ùÄ£¿é¿ÉÄܰüº¬ Áé¸ù»ù´¡¡¢Áé¸ùÆ·ÖÊ Á½¸ö¹¦ÄܵãÊôÐÔ
        
                    °Ù·Ö±È¼Ó³ÉÖµ£º°Ù·Ö±È¼Ó³ÉÊôÐÔÖµ²»±»³ýbuff°Ù·Ö±ÈÍâµÄÈκΰٷֱÈÊôÐÔ2´Î¼Ó³É
            1.¹¦ÄÜÄÚ²¿ÊôÐ԰ٷֱȼӳɣº¹¦ÄܰٷֱÈÊôÐÔ¶Ô×Ô¼º¹¦Ä̶ܹ¨Öµ¼Ó³É
            2.¹¦Äܽ»²æÊôÐ԰ٷֱȼӳɣº¹¦ÄܰٷֱÈÊôÐÔ¶ÔÆäËû¹¦Ä̶ܹ¨Öµ¼Ó³É
            3.¹¦Ä̶ܹ¨ÊôÐ԰ٷֱȼӳɣº¹¦ÄܰٷֱÈÊôÐÔ¶ÔËùÓй¦Ä̶ܹ¨Öµ¼Ó³É
            4.buff²ã¼¶°Ù·Ö±È£º¶ÔËùÓÐÊôÐÔ½øÐжþ´Î¼Ó³É
            
                    ¼¼ÄÜÊôÐÔ£º¹Ì¶¨Öµ²»ÏíÊ̶ܹ¨°Ù·Ö±È¼Ó³É
                    
        buff²ã¼¶£º
            1.²»ËãÕ½Á¦
            2.ÏÈËã°Ù·Ö±È¼Ó³ÉÔټӹ̶¨Öµ
            
                    ÊôÐÔËã·¨£º
                       Ä£¿é¹Ì¶¨ÊôÐÔ    = ¹¦ÄܵãA¹Ì¶¨Öµ + ¹¦ÄܵãB¹Ì¶¨Öµ + ...
                        ¹Ì¶¨×ÜÊôÐÔ        = Ä£¿éA¹Ì¶¨Öµ + Ä£¿éB¹Ì¶¨Öµ + ...
                        ÎÞbuff×ÜÊôÐÔ  = ¹Ì¶¨×ÜÊôÐÔ + ÄÚ²¿°Ù·Ö±È¼Ó³ÉÖµ + ½»²æ°Ù·Ö±È¼Ó³É  + ¹Ì¶¨×ÜÊôÐÔ°Ù·Ö±È¼Ó³É   + ¼¼ÄܰٷֱȶԹ̶¨ÊôÐÔ¼Ó³É  + ¼¼Ä̶ܹ¨Öµ
                        º¬buff×ÜÊôÐÔ  = ÎÞbuff×ÜÊôÐÔ * buff°Ù·Ö±È¼Ó³É  +  buff¹Ì¶¨Öµ
        '''
        curPlayer = self.__Player
        
        if curPlayer.GetDictByKey(ChConfig.Def_Player_RefreshAttr) != 1:
            return False
        
        PlayerGubao.CalcGubaoAttr(curPlayer) # ¹Å±¦¶¨Î»Îª¶Ô¹áͨËùÓÐÓÎÏ·¹¦ÄÜϵͳµÄÊôÐÔÍæ·¨£¬ËùÒÔÿ´Î¶¼ÖØÐÂË¢ÐÂ
        
        GameWorld.DebugLog("Start RefreshPlayerAttrStateEx!!!")
        
        #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)
        #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))
            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))
            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))
        GameWorld.DebugLog("¹¦ÄܵãÊôÐÔ: %s(%s), %s, ÄÚ²ã°Ù·Ö±È¸½¼Ó: %s" 
                           % (ChConfig.Def_CalcAttrFunc_LingGenQuailty, ChConfig.FuncIndexName.get(ChConfig.Def_CalcAttrFunc_LingGenQuailty, ""), lingGenQualityAttrList, lingGenQualityInsidePerAttrDict))
        
        #self.PrintAttr(curPlayer, "»ù´¡ºó")
        
        # 3.¼ÆËãÕ½¶·ÊôÐÔ
        #    3.1 Õ½¶·ÊôÐԲ㼶½»²æÓ°Ïì»ùÖµÊýÖµ»ã×Ü
        #        »ù´¡²ã¼¶(½ÇÉ«»ù´¡ÊôÐÔ)
        baseAttrList = AddAttrListValue([funcAttrInfoList[ChConfig.Def_CalcAttrFunc_RoleBase],
                                         funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LingGen],
                                         funcAttrInfoList[ChConfig.Def_CalcAttrFunc_LingGenQuailty],
                                         ])
        #GameWorld.DebugLog("»ù´¡²ã¼¶: %s" % baseAttrList)
        
        #        ¹¦Äܵ㽻²æÓ°Ïì·ÇÏßÐÔ²ã¶ÔÓ¦ÊôÐÔ»ùÖµÁбí
        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],
                           }
        #    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))
            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]
                useAttrDict = funcAttrPerInfo[noLineAttrType][ChConfig.CalcAttr_Battle] # ĬÈÏÔö¼ÓµÄÊÇÕ½¶·ÏßÐÔ
                for attrType in addAttrTypeList:
                    # ĬÈÏÌáÉýµÄÊôÐÔÔÚÏßÐÔÕ½¶·ÊôÐÔÀï
                    if attrType not in useAttrDict:
                        continue
                    baseValue = useAttrDict[attrType] # Ö»ÊÇÓõ½Ä¿±ê¹¦ÄܵĻùÖµ
                    addValue = int(baseValue * attrRate)
                    addAttrDict[attrType] = addAttrDict.get(attrType, 0) + addValue
                    #GameWorld.DebugLog("    attrID=%s,per=%s,rate=%s,baseValue=%s,attrType=%s,addValue=%s" % (noLineAttrType, addAttrPer, attrRate, baseValue, attrType, addValue))
                    
            if addAttrDict:
                # Ôö¼ÓµÄÊýֵͳ¼Æµ½°Ù·Ö±ÈÊôÐÔËùÊô¹¦Äܵã
                # Èç·ûÎÄÓиöÎäÆ÷¹¥»÷°Ù·Ö±ÈÔö¼ÓÊôÐÔ£¬Ôö¼ÓµÄÊýÖµÊôÓÚ·ûÎŦÄÜ£¬²»ÊôÓÚÎäÆ÷¹¦ÄܵãµÄ£¬Ö»ÊÇ»ùֵʹÓÃÁËÎäÆ÷¹¥»÷     
                funcCrossAttrPerInfoDict[i] = addAttrDict # Ïȶ¼Í³¼ÆÍêºóÔÙÀÛ¼Óµ½¶ÔÓ¦¹¦ÄÜÊôÐÔÀ²»È»¿ÉÄܻᵼÖ¹¦ÄÜ»ùÖµ±ä¸ü
                
        GameWorld.DebugLog("½»²æÓ°ÏìÊôÐÔ: %s" % funcCrossAttrPerInfoDict)
        
        #    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)
        GameWorld.DebugLog("¹Ì¶¨°Ù·Ö±È¸½¼ÓÊôÐÔ: %s" % fixAttrPerAddExDict)
        
        # 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 = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpObj.mfpType)
            mfpEx = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPEx % mfpObj.mfpType)
            mfpEx = GetMFPExFightPower(curPlayer, mfpType)
            mfpTotal = mfpValue + mfpSkill + mfpEx
            mfpDict[mfpObj.mfpType] = min(mfpTotal, ChConfig.Def_UpperLimit_DWord)
            
            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)
        
        # 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)
        
        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)
            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!!!")
        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))
        maxProDef = min(maxProDef, ChConfig.Def_UpperLimit_DWord)
        
        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
        allAttrListBuffs = [{} for _ in range(4)]
        # 6.¼ÆËãbuffÊôÐÔ, buff²ã¼¶µÄ²»ËãÈçÕ½¶·Á¦
        #        ËãÕ½¶·Á¦×Üֵʱ¸Ã²ãÓ°ÏìµÄÊýÖµ²»Í³¼Æ£¬µ«Ë¢ÊôÐÔʱÐè¼ÆËã
        SkillShell.CalcBuffers_Effect(curPlayer, allAttrListBuffs)
        # ¶É½Ù¸±±¾»¤·¨ÊôÐÔ¼Ó³É
        GameLogic_DuJie.CalcDujieFBAttrAdd(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)
        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:
            curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkill % 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 = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpType)
            curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkill % 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 = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpType)
        curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkill % 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 = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpType)
        curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPSkill % 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
        GameWorld.DebugLog("Õ½Á¦¹¦Äܵã: %s" % ChConfig.MFPTypeAttrFuncIndexDict)
        GameWorld.DebugLog("Ä£¿éÕ½Á¦: %s" % mfpDict)
        for mfpType, fightPower in mfpDict.items():
            SetMFPFightPower(curPlayer, mfpType, fightPower)
            mfpData = ChPyNetSendPack.tagMCModuleFightPower()
            mfpData.Clear()
            mfpData.MfpType = mfpType
            mfpData.FightPower = fightPower # µ±Ç°Ä£¿éÕ½¶·Á¦ÊýÖµ
            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))
        PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
        # ¼Ç¼¿ª·þ»î¶¯Êý¾Ý£¬¿ª·þ»î¶¯Ç°XÌìÀíÂÛÉϲ»»á³¬¹ý20E£¬Ôݲ»´¦Àí
        OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, min(totalFightPower, ChConfig.Def_UpperLimit_DWord))
        if beforeFightPower != totalFightPower:
            CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
        return
    
    def __RefreshMoveSpeed(self, allAttrListBuffs):
        ## Ë¢ÐÂÒÆ¶¯ËÙ¶È
        curPlayer = self.__Player
        
        moveSpeedFormat = IpyGameDataPY.GetFuncCfg("MoveSpeed")
        
        if PlayerTruck.GetHaveAutoTruck(curPlayer):
            speed = IpyGameDataPY.GetFuncCfg("MoveSpeed", 3)
            GameWorld.DebugLog("ÔËïڹ̶¨ËÙ¶ÈÖµ: speed=%s" % speed)
        else:
            speed = GetSpeedNotBuff(curPlayer)
            GameWorld.DebugLog("¹¦ÄÜÒÆ¶¯ËÙ¶ÈÖµ: speed=%s" % speed)
            
            # Æï³Ë״̬¼ÓÉÏÆï³Ë¸½¼ÓËÙ¶È
            if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
                speedHorse = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SpeedHorse)
                speed += speedHorse
                GameWorld.DebugLog("    Æï³Ë״̬¸½¼ÓÖµ: %s, speed=%s" % (speedHorse, speed))
            
                
            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))
                
            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)
            
            fightPet = curPlayer.GetPetMgr().GetFightPet()
            #ÎÞ³öÕ½³èÎï
            if fightPet:
                fightPet.SetSpeed(moveSpeed)
                
        return
    ##ˢй¥»÷¼ä¸ô
    # @param self ÀàʵÀý
    # @return None
    def __SetAtkInterval(self):
        curPlayer = self.__Player
        
        atkSpeed = GameObj.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):
        GameWorld.DebugLog("Start RefreshPlayerActionState!!!")
        #curTime = time.clock()
        curPlayer = self.__Player
        
        #ÏÈÇå³ýËùÓÐ״̬
        OperControlManager.ClearObjActionState(curPlayer)
        
        #ÔÙ¸ù¾ÝBUFF ¼ÓÉÏ״̬
        SkillShell.CalcBuffer_ActionState(curPlayer)
    
    #---------------------------------------------------------------------
    ## Ë¢ÐÂѪÁ¿ºÍħ
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Ë¢ÐÂѪÁ¿ºÍħ
    def __RestoreHPMP(self):
        curPlayer = self.__Player
        
        if not curPlayer.GetInitOK():
            #Íæ¼Òδ³õʼ»¯³É¹¦, ²»ÐÞÕýѪÁ¿ºÍħ·¨Öµ, Òò´ËʱÓпÉÄÜÒòΪijЩӰÏìÖ÷½ÇµÄÎïÆ·Î´³õʼ»¯Íê±Ï(Èç³èÎï×°±¸)
            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
    
    #---------------------------------------------------------------------
    ## ½«Íæ¼ÒÉèÖõ½ÖØÉúµã
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks ½«Íæ¼ÒÉèÖõ½ÖØÉúµã
    def SetToBornPlace(self):
        curPlayer = self.__Player
        mapFBType = GameWorld.GetMap().GetMapFBType()
        #Íæ¼Ò²»ÔÚ¸±±¾ÖÐ
        if mapFBType == IPY_GameWorld.fbtNull:
#            gameMap = GameWorld.GetMap()
#            rebornMapID = gameMap.GetRebornMapID()
#            rebornPosX = gameMap.GetRebornMapX()
#            rebornPosY = gameMap.GetRebornMapY()
#            
#            #ÑéÖ¤ÊÇ·ñ±¾µØÍ¼¸´»îµã ½øÐÐÂß¼´¦Àí
#            if gameMap.GetMapID() == rebornMapID:
#                posX, posY = GameMap.GetNearbyPosByDis(rebornPosX, rebornPosY, ChConfig.Def_RebornPos_Area_Range)
#            else:
#                posX, posY = rebornPosX, rebornPosY
#                
#            #ÕÒ²»µ½·ÇÕϰµã¸´»î£¬ÔòÉèÎªÍæ¼ÒµÄÖØÉúµã¸´»î
#            if posX <= 0 or posY <= 0 or rebornMapID <= 0:
#                rebornMapID = curPlayer.GetRebornMapID()
#                posX = curPlayer.GetRebornPosX()
#                posY = curPlayer.GetRebornPosY()
            rebornMapID = curPlayer.GetRebornMapID()
            rebornPosX = curPlayer.GetRebornPosX()
            rebornPosY = curPlayer.GetRebornPosY()
        #Íæ¼ÒÔÚ¸±±¾ÖÐ
        else:
            rebornMapID = curPlayer.GetFBRebornMapID()
            rebornPosX = curPlayer.GetFBRebornPosX()
            rebornPosY = curPlayer.GetFBRebornPosY()
        
        if rebornMapID == 0:
            NotifyCode(curPlayer, "ObjectMapNonentity")
            GameWorld.Log("ÈËÎïÖØÉúµØÍ¼ID = %sÒì³£!" % (rebornMapID) , curPlayer.GetPlayerID())
            return
        
        if rebornMapID == curPlayer.GetMapID():
            GameWorld.ResetPlayerPos(curPlayer, rebornPosX, rebornPosY)
            return
        
        #°ÑÈËÎïÉèÖûØÖØÉúµã
        PlayerResetWorldPos(curPlayer, rebornMapID, rebornPosX, rebornPosY, False)
        return
    
    #---------------------------------------------------------------------
    ## Íæ¼ÒËÀÍöÂß¼
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Íæ¼ÒËÀÍöÂß¼
    def SetDead(self):
        #Ö÷½ÇÉèÖÃΪËÀÍö״̬
        curPlayer = self.__Player
        
        #֪ͨ¸±±¾Íæ¼ÒËÀÍö
        FBLogic.DoPlayerDead(curPlayer)
        
        #Íæ¼Ò״̬´¦Àí
        ReSetPlayerState(curPlayer)
        
        #Çå¿ÕËùÓÐËÀÍö²»±£ÁôµÄbuff
        self.__PlayerDeadClearBuff()
        #ɱËÀËùÓÐÕÙ»½µÄÁé
        KillPlayerSummonNPC(curPlayer)
        
        #ÕÙ»½»Ø³öÕ½µÄ³èÎï
        PetControl.ReCallFightPet(curPlayer)
        
        #ÀïÚÍæ¼ÒËÀÍö´¦Àí
        PlayerTruck.DoPlayerDead(curPlayer)
        #Çå¿ÕʹÓü¼ÄܼǼ
        curPlayer.ClearUseSkillRec()
        
        #¸ÄΪ¸´»îµÄʱºòË¢ÐÂ״̬
#===============================================================================
#        #Ë¢ÐÂ״̬
#        self.RefreshAllState()
#===============================================================================
        
        if GameObj.GetHP(curPlayer) != 0:
            GameObj.SetHP(curPlayer, 0)
        
        #Çå¿ÕÒÆ¶¯´íÎó¾àÀë
        GameWorld.ClearPlayerPosCount(curPlayer)
        
        #¼Ç¼Ö÷½ÇËÀÍö´ÎÊýºÍËÀÍöʱ¼ä
        self.SetPlayerDeadCnt(curPlayer)
        
        #ËÀÍö´¥·¢¼¼ÄÜ
        tick = GameWorld.GetGameWorld().GetTick()
        
        #֪ͨËÀÍö
        DoPlayerDead(curPlayer)
        
        #PlayerTJG.PlayerTJGReborn(curPlayer, tick)
        GameObj.ClearPyPlayerState(curPlayer)
        return
    
    
    ## ¼Ç¼Ö÷½ÇËÀÍö´ÎÊý
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    def SetPlayerDeadCnt(self, curPlayer):
        #playerLv = curPlayer.GetLV()
        #¼Ç¼ËÀÍöʱ¼ä
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_DeadTime, int(time.time()))
        #ÉíÉÏÓÐ5²ã¸´»îÆ£ÀÍbuffʱÔټǼ
        findBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_ReviveTired)[0]
        if not (findBuff and findBuff.GetSkill().GetSkillLV() == findBuff.GetSkill().GetSkillMaxLV()):
            return
        
#        if playerLv < int(ReadChConfig.GetEvalChConfig('BeginRecordDeadCntLV')):
#            return
        
        #ÉϴμǼµÄÍæ¼ÒËÀÍö´ÎÊý
#         lastDeadCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_PlayerDeadCnt)
#         #GameWorld.Log("ÉÏ´ÎÍæ¼ÒËÀÍö´ÎÊý=%s"%lastDeadCnt)
#         
#         #ËÀÍö´ÎÊý×î´óÀÛ¼ÓÖµ
#         maxDeadCnt = int(ReadChConfig.GetEvalChConfig('PlayerDeadMaxCnt'))
#         
#         #»ñÈ¡ÉÏ´ÎËÀÍöʱ¼ä
#         lastDeadTimeTick = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)
#         #GameWorld.Log("»ñÈ¡ÉÏ´ÎËÀÍöʱ¼ä=%s"%lastDeadTimeTick)
#         
#         #ÿ¸ô¼¸ºÁÃë¼õÒ»´ÎËÀÍö´ÎÊý
#         timeSpace = int(ReadChConfig.GetEvalChConfig('DelDeadCntTime')) 
#         
#         #µ±Ç°Ê±¼ä
#         curGameWorldTick = int(time.time())
#         delCnt = max(curGameWorldTick - lastDeadTimeTick, 0) / timeSpace
#         
#         #GameWorld.Log("###delCnt=%s"%delCnt)
#         #µ±Ç°ËÀÍö´ÎÊý(°üÀ¨Õâ´ÎËÀµÄ)
#         curDeadCnt = min(max(lastDeadCnt - delCnt, 0) + 1, maxDeadCnt)
#         
#         #GameWorld.Log("###curDeadCnt=%s"%curDeadCnt)
#         #GameWorld.Log("###curTimeTick=%s"%curGameWorldTick)
#         #¼Ç¼µ±Ç°ËÀÍö´ÎÊý
#         NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_PlayerDeadCnt, curDeadCnt)
        
        #֪ͨËÀÍöʱ¼ä
        self.NotifyPlayerDeadTime(curPlayer)
        return
    
    ## ֪ͨÉÏ´ÎËÀÍöʱ¼ä
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Íæ¼ÒËÀÍöÂß¼, ºìÃûµôÂä
    def NotifyPlayerDeadTime(self, curPlayer):
        #Èç¹ûÓÐ5²ã¸´»îÆ£ÀÍbuff ²¢ÇÒÊDZ»Íæ¼ÒɱËÀµÄÔò֪ͨ
        findBuff = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_ReviveTired)[0]
        if findBuff and findBuff.GetSkill().GetSkillLV() == findBuff.GetSkill().GetSkillMaxLV():
            if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_IsAddReviveTired):
                lastDeadTimeTick = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)
                packData = ChPyNetSendPack.tagMCPlayerDeadTime()
                packData.DeadTime = lastDeadTimeTick
                NetPackCommon.SendFakePack(curPlayer, packData)
        return
    
    #---------------------------------------------------------------------
    ## Çå¿ÕËùÓеĿÉÒÔɾ³ýµÄbuff
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Çå¿ÕËùÓеĿÉÒÔɾ³ýµÄbuff
    def __PlayerDeadClearBuff(self):
        curPlayer = self.__Player
        tick = GameWorld.GetGameWorld().GetTick()
        
        #ÐèÒª¿¼ÂÇbuff,deBuff,aura,incBuff,mapBuff,³ýÁËequipBuff²»¿¼ÂÇ
        PlayerClearBuff_Single(curPlayer, curPlayer.GetBuffState(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetDeBuffState(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetAura(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetIncBuff(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetMapBuff(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetActionBuffManager(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetProcessBuffState(), ClearBuffByDie, tick)
        PlayerClearBuff_Single(curPlayer, curPlayer.GetProcessDeBuffState(), ClearBuffByDie, tick)
        
        return
    
#---------------------------------------------------------------------
## Çå¿Õbuff(²ÎÊý -> buff¹ÜÀíÆ÷)
#  @param curPlayer Íæ¼ÒʵÀý
#  @param buffState buff¹ÜÀíÆ÷
#  @param tick ʱ¼ä´Á
#  @return ·µ»ØÖµÎÞÒâÒå
#  @remarks Çå¿Õbuff(²ÎÊý -> buff¹ÜÀíÆ÷)
def PlayerClearBuff_Single(curPlayer, buffState, funcClearBuff, tick):
    curPlayerID = curPlayer.GetPlayerID()
    index = 0
    buffSkillIDList = []
    
    passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(curPlayer)
    while index < buffState.GetBuffCount():
        curBuff = buffState.GetBuff(index)
        #Òì³£
        if not curBuff:
            GameWorld.Log("###Íæ¼ÒÇå¿Õbuffʧ°Ü,Ë÷Òý = %s" % (index), curPlayerID)
            index += 1
            continue
        
        #buff²»Ïûʧ
        if funcClearBuff and funcClearBuff(curBuff):
            index += 1
            continue
        
        #BuffSkill.DoBuffDisApper(curPlayer, curBuff, tick)
        #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
## ËÀÍöbuffÊÇ·ñÏûʧ
#  @param curBuff: buffʵÀý
#  @return: ËÀÍöbuffÊÇ·ñÏûʧ
def ClearBuffByDie(curBuff):
    skill = curBuff.GetSkill()
    return skill.GetDieContinue() & Def_Buff_Clear_Die > 0
## ÏÂÏßbuffÊÇ·ñÏûʧ
#  @param curBuff: buffʵÀý
#  @return: ËÀÍöbuffÊÇ·ñÏûʧ
def ClearBuffByDisconnect(curBuff):
    skill = curBuff.GetSkill()
    return skill.GetDieContinue() & Def_Buff_Clear_Disconnect > 0
            
#---------------------------------------------------------------------
##´«Ëͼì²é(ÊÇ·ñ·Ç·¨µØÍ¼)
# @param curPlayer Íæ¼ÒʵÀý
# @param destMapID Ä¿±êµØÍ¼ID
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks ´«Ëͼì²é
def CheckTagCountry(curPlayer, destMapID):
    gameMap = GameWorld.GetMap()
    
    if not gameMap.IsMapIDExist(destMapID):
        GameWorld.ErrLog('###·Ç·¨µØÍ¼Êý¾Ý£¬mapID: %s' % (destMapID), curPlayer.GetPlayerID())
        NotifyCode(curPlayer, "ObjectMapNonentity")
        return False
    
#===============================================================================
#    #ÐÂÊִ峡¾°²»ÔÊÐí½øÈëºÍ´«³ö
#    if GameWorld.GetMap().GetMapID() == 21 or destMapID == 21:
#        NotifyCode(curPlayer, "CS_VillageHead_Fail")
#        return 
#===============================================================================
    
    #¼ì²éÍæ¼ÒÊÇ·ñ´«Ë͵йú×ø±ê
    mapCountry = gameMap.GetCountryByMapID(destMapID)
    
    if not GameWorld.IsSameCountry_Name(mapCountry, curPlayer.GetCountry()):
        NotifyCode(curPlayer, "Enemy_State_No_Trans")
        return False
    
    #¼ì²é´«ËÍÖÁµÄµØÍ¼ÊÇ·ñÊÇÆÕͨµØÍ¼
    if gameMap.GetMapFBTypeByMapID(destMapID) != IPY_GameWorld.fbtNull:
        #¸±±¾ºÍ»î¶¯³¡¾°ÎÞ·¨´«ËÍ
        NotifyCode(curPlayer, "Carry_lhs_306641")
        return False
    
    #¼ì²éÍæ¼ÒµÈ¼¶ÊÇ·ñ×ã¹»½øÈë´ËµØÍ¼
    if not CanEnterMap(curPlayer, destMapID):
        return False
    
    #¼ì²é´ËµØÍ¼ÊÇ·ñΪָ¶¨·ÖÁ÷ÓµÓеÄ
    mapLineID = GetPlayerLineID(curPlayer)
    
    mapLineCheckDict = ReadChConfig.GetEvalChConfig('TransportMapLineCheck')
    canEnterLineID = 0
    
    for lineID, mapIDList in mapLineCheckDict.items():
        if destMapID not in mapIDList:
            continue
        
        if mapLineID == lineID:
            #´Ë·ÖÁ÷¿ÉÒÔ½øÈë
            return True
        #¼Ç¼һÏ¿ÉÒÔ½øÈëµÄÏß·
        canEnterLineID = lineID
    if canEnterLineID > 0:
        #´Ë·ÖÁ÷²»¿É½øÈë
        NotifyCode(curPlayer, "Carry_yeqian_0", [destMapID, canEnterLineID])
        return False
    #¿ÉÒÔ½øÈë
    return True
#---------------------------------------------------------------------
##²éÍæ¼ÒµÈ¼¶ÊÇ·ñ×ã¹»½øÈë´ËµØÍ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param destMapID Ä¿±êµØÍ¼ID
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks ²éÍæ¼ÒµÈ¼¶ÊÇ·ñ×ã¹»½øÈë´ËµØÍ¼
def CanEnterMap(curPlayer, destMapID, isShowSys=True):
    #µØÍ¼ÌØÊâ¼ì²é
    #if not CheckEquipCanTrans(curPlayer, destMapID):
        #return False
    
    if not CheckLVCanEnterMap(curPlayer, destMapID, isShowSys):
        return False
    
    return True
    
##²éÍæ¼ÒµÈ¼¶ÊÇ·ñ×ã¹»½øÈë´ËµØÍ¼
# @param curPlayer Íæ¼ÒʵÀý
# @param destMapID Ä¿±êµØÍ¼ID
# @return ·µ»ØÖµÕæ, ͨ¹ý
def CheckLVCanEnterMap(curPlayer, destMapID, isShowSys=True):
    mapData = GameWorld.GetGameData().GetChinMap().GetMapByID(destMapID)
    if not mapData:
        return 
    enterLV = mapData.GetLV()
    if curPlayer.GetLV() < enterLV:
        #¶Ô²»Æð£¬¸Ã³¡¾°ÐèÒªXX¼¶²ÅÄܽøÈë!
        if isShowSys:
            NotifyCode(curPlayer, "Carry_hwj35_0", [enterLV])
        return False
    openMapStep = mapData.GetTreasureID() #ÐèÒªÍê³ÉµÄÖ÷ÏßÈÎÎñID
    if openMapStep and not IsMapOpen(curPlayer, openMapStep):
        #GameWorld.DebugLog('¶Ô²»Æð£¬¸Ã³¡¾°destMapID=%sÐèÒªÍê³ÉÖ÷ÏßÈÎÎñ%s²ÅÄܽøÈë!' % (destMapID, openMapStep))
        return False
    return True
def IsMapOpen(curPlayer, openMapStep):
    # Ö÷ÏßÈÎÎñÍê³Éʱ»áÉèÖñêÖ¾¿É½øµØÍ¼±êÖ¾
    mission_1 = QuestCommon.GetCommonMission(curPlayer)
    if not mission_1:
        return False
    if openMapStep > mission_1.GetProperty("OpenMap"):
        return False
    return True
#---------------------------------------------------------------------
##¹ØÓÚ´«ËÍ ÑéÖ¤Íæ¼Ò״̬
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks ¹ØÓÚ´«ËÍ ÑéÖ¤Íæ¼Ò״̬
def CheckTransState(curPlayer):
    #¿ÉÒÔ½øÈë´«Ë͵Ä״̬
    playerAction = curPlayer.GetPlayerAction()
    if playerAction in ChConfig.Def_Player_Cannot_TransState:
        #Carry_lhs_697674£ºÄúµ±Ç°Ëù´¦µÄ״̬²»ÄܽøÐд«ËÍ!
        NotifyCode(curPlayer, "Carry_lhs_697674")
        return False
    
    #ÒÆ¶¯Öв»Ö´Ðд˲Ù×÷
    if curPlayer.IsMoving():
        curPlayer.StopMove()
    
    
    if playerAction == IPY_GameWorld.paSit:
        DoPlayerStand(curPlayer)
    
    #ÇëÇó´«ËÍ״̬, ÅжϷþÎñ¶ËÏÞÖÆ
    if not OperControlManager.IsObjCanDoAction(
                                        curPlayer,
                                        ChConfig.Def_Obj_ActState_ServerAct,
                                        IPY_GameWorld.oalTransmit
                                        ):
        return False
    
    return True 
#---------------------------------------------------------------------
##Çå³ýÓÐÏÞÎÞµÐBUF
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Çå³ýÓÐÏÞÎÞµÐBUF
def DelLimitSuperBuff(curPlayer, tick):
    if curPlayer.GetCanAttack():
        return
    
    if not tick:
        tick = GameWorld.GetGameWorld().GetTick()
        
    if BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_LimitSuperBuff, tick):
    
        PlayerControl(curPlayer).RefreshPlayerAttrByBuff()
    
#---------------------------------------------------------------------
##ÌØÊâ״̬´¦Àí
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ÌØÊâ״̬´¦Àí
def ReSetPlayerState(curPlayer):
    tick = GameWorld.GetGameWorld().GetTick()
    
    #---Íæ¼Ò״̬´¦Àí---
    curPlayerAction = curPlayer.GetPlayerAction()
    
    #Íæ¼Ò½»Ò×ÖÐ, À뿪½»Ò×
    if curPlayerAction == IPY_GameWorld.paTrade:
        PlayerTrade.LeaveTrade(curPlayer, 0)
                    
    #Íæ¼Òʼþ״̬ÖÐ, Í˳öʼþ
    elif curPlayerAction == IPY_GameWorld.paEvent:
        EventShell.DoExitEvent(curPlayer)
        
    elif curPlayerAction == IPY_GameWorld.paGameEvent:
        PlayerGameEvent.StopGameEvent(curPlayer, tick)
        
    if curPlayerAction == IPY_GameWorld.paPreparing:
        DoExitPreparing(curPlayer)
    
    #---Íæ¼Ò½»Í¨¹¤¾ß´¦Àí---
    curPlayerVehicle = curPlayer.GetPlayerVehicle()
    
    #Íæ¼ÒÆïÂíÖÐ, ÏÂÂí
    if curPlayerVehicle == IPY_GameWorld.pvHorse:
        #Ö´ÐÐÏÂÂíÂß¼
        PlayerHorse.PlayerRideHorseDown(curPlayer, False)
        
    #Íæ¼ÒïÚ³µÖÐ, ϳµ
    elif curPlayerVehicle == IPY_GameWorld.pvTruck:
        PlayerTruck.PlayerTruckDown(curPlayer, curPlayer.GetTruck())
    
    #---ÆäËûϵͳ´¦Àí---
    
    #ÖжÏÕ½¶·¶ÔÖÅ
    ExitPlayerConfronting(curPlayer)
    
    #Çå¿Õµ±Ç°¹¥»÷¶ÔÏó
    curPlayer.SetActionObj(None)
    return
#---------------------------------------------------------------------
##³õʼ»¯Öк͵ØÍ¼¶Áȡʱ²»À»Ø
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ³õʼ»¯Öк͵ØÍ¼¶Áȡʱ²»À»Ø
def __CanPullPlayer(curPlayer):
    if not curPlayer.GetInitOK():
        return False
    
    if curPlayer.GetIsLoginOff():
        return False
    
    return True
#------------------------------------------------------------------------------------ 
##·µ»ØÍæ¼Òµ±Ç°ÊÇ·ñÔÚ¿ÕÏÐ״̬
# @param curPlayer Íæ¼ÒʵÀý
# @return ÊÇ·ñÔÚ¿ÕÏÐ״̬
# @remarks ·µ»ØÍæ¼Òµ±Ç°ÊÇ·ñÔÚ¿ÕÏÐ״̬£¨²ß»®²ãÃæÉϵĿÕÏУ©
def IsPlanStateNull(curPlayer):
    
    #·Ç¿ÕÏÐ״̬
    if curPlayer.GetPlayerAction() != IPY_GameWorld.paNull:
        return False
    
    #ÒÆ¶¯ÖÐ
    if curPlayer.IsMoving():
        return False
    
    #Õ½¶·ÖÐ
    if curPlayer.IsBattleState():
        return False
    
#    #¶ÔÖÅÖÐ
#    if curPlayer.GetIsConfronting():
#        return False
    
#    #Ñ£ÔÎÖÐ
#    if curPlayer.GetAbnormalState() == IPY_GameWorld.sctFaint:
#        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 = ChConfig.Def_PlayerFirstLoginOpenBackCnt + 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
    
    #»ñÈ¡Íæ¼Ò±³°ü
    curPack = curPlayer.GetItemManager().GetPack(packType)
    
    #ĬÈÏ42¸ñ×Ó + ¿ªÆôµÄ
    keyName = ChConfig.Def_Type_CanBuyPack_PlayerDict.get(packType)[ChConfig.Def_PlayerPackDict_Index_Key]
    count = ChConfig.Def_FirstLogin_OpenWareHouseCnt + 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(ChConfig.Def_PackCnt_Treasure)
    
    #֪ͨ¿Í»§¶Ë
    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=""):
    ## Íæ¼ÒÊÇ·ñÓÐÕýÔÚ½øÐÐÖÐÔËÓª»î¶¯£¬²»º¬²ÎÓë½áÊø½×¶Î
    
    if crossActName and crossActIDKey:
        playerActID = curPlayer.NomalDictGetProperty(crossActIDKey)
        actInfo = CrossRealmPlayer.GetPlayerCrossActInfo(curPlayer, crossActName)
        actID = actInfo.get(ShareDefine.ActKey_ID, 0)
        cfgID = actInfo.get(ShareDefine.ActKey_CfgID, 0)
        state = actInfo.get(ShareDefine.ActKey_State, 0)
        stateJoin = actInfo.get(ShareDefine.ActKey_StateJoin, 0)
        if state and stateJoin != ShareDefine.ActStateJoin_End and actID == playerActID:
            GameWorld.DebugLog("%s»î¶¯Íæ¼ÒÕýÔÚ²ÎÓëÖÐ! cfgID=%s,actID=%s,stateJoin=%s" 
                               % (crossActName, cfgID, actID, stateJoin), curPlayer.GetPlayerID())
            return True
        
    for actInfo in PyGameData.g_operationActionDict.get(actName, {}).values():
        actNum = actInfo.get(ShareDefine.ActKey_ActNum, 0)
        actID = actInfo.get(ShareDefine.ActKey_ID, 0)
        state = actInfo.get(ShareDefine.ActKey_State, 0)
        stateJoin = actInfo.get(ShareDefine.ActKey_StateJoin, 0)
        playerActID = curPlayer.NomalDictGetProperty(actIDKey % actNum)
        if state and stateJoin != ShareDefine.ActStateJoin_End and actID == playerActID:
            GameWorld.DebugLog("%sÍæ¼ÒÕýÔÚ²ÎÓëÖÐ! actNum=%s,actID=%s,stateJoin=%s" 
                               % (actName, actNum, actID, stateJoin), curPlayer.GetPlayerID())
            return True
        
    return False
def RefreshOperationAction_ExpRate():
    playerManager = GameWorld.GetPlayerManager()
    for i in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(i)
        if curPlayer == None or not curPlayer.GetInitOK():
            continue
        Sync_ExpRateChange(curPlayer)
    return
##Í¨ÖªÍæ¼Ò¾Ñé±¶ÂÊ
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Í¨ÖªÍæ¼Ò¾Ñé±¶ÂÊ
def Sync_ExpRateChange(curPlayer):
    totalExpRate = GetPlayerExpRate(curPlayer)
    fightExpRate = curPlayer.GetFightExpRate() # ϵͳ¼°¹¦ÄÜÀÛ¼Ó
    fightExpRate += PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer) # ÊÀ½çµÈ¼¶
    fightExpRate += PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_FightExpRate) # VIP¼Ó³É
    
    actExpRateInfo = PyGameData.g_operationActionDict.get(ShareDefine.OperationActionName_ExpRate, {})# ¶à±¶¾Ñé»î¶¯¼Ó³É
    if not PlayerTJG.GetIsTJG(curPlayer) and actExpRateInfo.get(ShareDefine.ActKey_State):
        actExpIpyData = IpyGameDataPY.GetIpyGameData("ActExpRate", actExpRateInfo.get(ShareDefine.ActKey_CfgID))
        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) # ×é¶Ó
    
    #µØÍ¼¶à±¶¾Ñé¼Ó³É£¬Ä¬ÈÏÊÇ1±¶²»¼Ó³É
    mapExpAddMultiple = max(0, FBCommon.GetAreaRewardMultiple(curPlayer) - 1)
    fightExpRate += mapExpAddMultiple * ChConfig.Def_MaxRateValue
    
    if totalExpRate != fightExpRate:
        curPlayer.SetDict(ChConfig.Def_PlayerKey_TotalExpRate, fightExpRate)
        curPlayer.Sync_CurExpRate(fightExpRate)
    return
##»ñÈ¡Íæ¼ÒµÄ¾Ñé±¶ÂÊ
def GetPlayerExpRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TotalExpRate)
def GetLimitExpRate(curPlayer, limitType=None):
    ''' »ñÈ¡ÊÜÏÞ¹¦ÄÜ×ܾÑé±¶ÂÊ
    @param limitType: ÊÜÏ޵ŦÄÜÀàÐÍ
    '''
    totalExpRate = GetPlayerExpRate(curPlayer)
    if limitType == None:
        return totalExpRate
    
    # ¿Û³ýÔöÖµbuffÖжÔÓ¦ÏÞÖÆµÄ¼Ó³É
    buffState = curPlayer.GetIncBuff()
    for i in xrange(buffState.GetBuffCount()):
        curBuff = buffState.GetBuff(i)
        buffSkill = curBuff.GetSkill()
        for j in range(buffSkill.GetEffectCount()):
            curEffect = buffSkill.GetEffect(j)
            effectID = curEffect.GetEffectID()
            if effectID == 0:
                break
            
            if effectID != ChConfig.TYPE_Calc_AttrFightExpRate:
                continue
            
            effExpRate = curEffect.GetEffectValue(0)
            calcType = curEffect.GetEffectValue(1)
            limitTypeValue = curEffect.GetEffectValue(2) # °´Î»¼ÆËã
            
            if calcType != ChConfig.EffCalcType_LinePlus or not limitTypeValue:
                continue
            
            if limitTypeValue & pow(2, limitType):
                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
#===============================================================================
#---Íæ¼ÒÀ©Õ¹×Ö¶Î---
#---À©Õ¹×Ö¶Î2,3,5,9,12,13,14---
#---À©Õ¹×Ö¶Î1-Ö°Òµ½×¼¶£»4-µ±Ç°·À»¤Öµ£»6-ÍÇ®µã£»7-SPÕæÆøÖµ£»8-SPÕæÆøÖµÀ©Õ¹µã£»10-¿ç·þÔ¤ÈüÅÅλ£»11-¹Ù¾ôÐǼ¶£»---
# 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, int inputValueEx, bool boardCast, bool includeSelf = true)
# @param : boardCast-ÊÇ·ñ¹ã²¥ÖÜÎ§Íæ¼Ò£»includeSelf-ÊÇ·ñ°üº¬×Ô¼º
#
# ֪ͨGsmeServer; 
# SendGameServerRefreshState(int inputType, int inputValue, int inputValueEx)
def SendPropertyRefresh(curPlayer, inputType, value, boardCast=False):
    ''' ·¢ËÍ0418°ü
    @param boardCast: ÊÇ·ñ¹ã²¥ÖÜÎ§Íæ¼Ò£¬Ò»¶¨»á·¢¸ø×Ô¼º
    '''
    curPlayer.SendPropertyRefresh(inputType, value % ShareDefine.Def_PerPointValue, value / ShareDefine.Def_PerPointValue, boardCast)
    return
def SendGameServerRefreshState(curPlayer, inputType, value):
    ## ͬ²½ÊôÐÔµ½GameServer IPY_GRefreshPlayerProperty
    curPlayer.SendGameServerRefreshState(inputType, value % ShareDefine.Def_PerPointValue, value / ShareDefine.Def_PerPointValue)
    return
# ½ûÑÔ Í¨ÖªgameServer
def SetGMForbidenTalk(curPlayer, value):
    ''' ÉèÖÃÊÇ·ñ½ûÑÔ
    @param value: 0-½â½û£»1-½ûÑÔ£»2-½ûÉ豸£»3-½âÉ豸
    
    ½ûÉ豸Á÷³Ì
    1.ÏÈÉèÖÃ2֪ͨǰ¶ËдÈë½ûÉ豸¼Ç¼£¨Ç°¶Ë´¦Àíµ±Îª2ʱ±¾µØÉ豸±ê¼ÇΪ½ûÉ豸£© 
    2.ÔÙÉèÖÃ1£¬´Ëʱǰºó¶Ë״̬¾ùΪ1£¬¼´½ÇÉ«½ûÑÔ
    
    ½â½ûÉ豸Á÷³Ì
    1.ÏÈÉèÖÃ3֪ͨǰ¶Ëɾ³ý½ûÉ豸¼Ç¼
    2.ÔÙÉèÖÃ0£¬´Ëʱǰºó¶Ë״̬¾ùΪ1£¬¼´½ÇÉ«½â½û
    '''
    __SetGMForbidenTalkValue(curPlayer, value)
    
    #ͬ²½ÉèÖÃÀëÏßDBÍæ¼ÒÕ˺Å״ֵ̬
    accState = curPlayer.GetAccState()
    if value == 2:
        accState = accState | pow(2, ChConfig.Def_PysForbidTalkDevice)
        accState = accState | pow(2, ChConfig.Def_PysForbidTalk)
    elif value == 1:
        accState = accState | pow(2, ChConfig.Def_PysForbidTalk)
    elif value == 3:
        if (accState & pow(2, ChConfig.Def_PysForbidTalkDevice)):
            accState = accState ^ pow(2, ChConfig.Def_PysForbidTalkDevice)
        if (accState & pow(2, ChConfig.Def_PysForbidTalk)):
            accState = accState ^ pow(2, ChConfig.Def_PysForbidTalk)
    elif (accState & pow(2, ChConfig.Def_PysForbidTalk)) > 0:
        accState = accState ^ pow(2, ChConfig.Def_PysForbidTalk)
    SetPlayerAccState(curPlayer, accState)
    return
def __SetGMForbidenTalkValue(curPlayer, value):
    curPlayer.SetGMForbidenTalk(value)
    SendGameServerRefreshState(curPlayer, ShareDefine.CDBPlayerRefresh_ForbidenTalk, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ForbidenTalk, value)
    GameWorld.DebugLog("__SetGMForbidenTalkValue %s" % value, curPlayer.GetPlayerID())
    return
def SetPlayerAccState(curPlayer, accState):
    curPlayer.SetAccState(accState)
    curPlayer.SetExAttr17(accState) # ͬ²½ÉèÖøÃÖµ 0309 ·â°üµÇ¼ʱÐèÒªÓõ½
    SendGameServerRefreshState(curPlayer, ShareDefine.CDBPlayerRefresh_ExAttr17, accState)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ExAttr17, accState)
    GameWorld.DebugLog("SetPlayerAccState %s" % (accState), curPlayer.GetPlayerID())
    return
def DoGMForbidenTalkOnLogin(curPlayer):
    ## ÀëÏßʱ±»½ûÑÔ£¬´ËʱDBµÄÕ˺Å״ֵ̬Ϊ½ûÑÔ״̬£¬µ«ÊÇGMOperÔÝʱûÓнûÑÔ²Ù×÷ÃüÁ¹ÊÉÏÏßʱ¼ì²éÉèÖÃÏÂÀëÏß½ûÑÔ״̬
    ## ĿǰÀëÏßʱ±»½ûÑԵģ¬ÔÝʱֻ´¦ÀíAccState ExAttr17, GMOperÃüÁîÔݲ»´¦Àí£¬ËùÒÔΪÓÀ¾Ã½ûÑÔ
    
    if curPlayer.GetAccState() & pow(2, ChConfig.Def_PysForbidTalkDevice):
        GameWorld.Log("ÉÏÏßʱ½ÇɫΪ±»É豸½ûÑÔ״̬!", curPlayer.GetPlayerID())
        __SetGMForbidenTalkValue(curPlayer, 2)
        __SetGMForbidenTalkValue(curPlayer, 1)
    elif curPlayer.GetAccState() & pow(2, ChConfig.Def_PysForbidTalk):
        GameWorld.Log("ÉÏÏßʱ½ÇɫΪ±»½ûÑÔ״̬!", curPlayer.GetPlayerID())
        __SetGMForbidenTalkValue(curPlayer, 1)
    else:
        SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ForbidenTalk, 0)
    return
## ÐÖúÄ¿±êÍæ¼ÒID
def SetAssistTagPlayerID(curPlayer, value):
    curPlayer.SetExAttr1(value, True, False) # ²»Í¨ÖªGameServer
    NPCHurtManager.OnSetAssistTagPlayerID(curPlayer, value)
    return
def GetAssistTagPlayerID(curPlayer): return curPlayer.GetExAttr1()
## ¶ÓÎéÏà¹ØÉóºË¿ª¹Ø×´Ì¬, 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()
## ¸±±¾¹¦ÄÜÏß·ID, ÕâÀï×ödb´æ´¢£¬·ÀÖ¹Ôںϲ¢µØÍ¼¸±±¾ÖеôÏßÖØÉÏʱǰ¶ËÎÞ·¨¼ÓÔØÕýÈ·µÄ³¡¾°×ÊÔ´£¬µÇ¼¼ÓÔØ³¡¾°Ê±»úΪ0102°ü
def SetFBFuncLineID(curPlayer, funcLineID): return curPlayer.SetExAttr3(funcLineID, False, True)
def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3()
## ¿ç·þ״̬ËùÔÚµØÍ¼ID: 0-·Ç¿ç·þ״̬£¬·Ç0-¿ç·þ״̬¶ÔÓ¦µÄµØÍ¼ID
def GetCrossMapID(curPlayer): return curPlayer.GetExAttr5()
def SetCrossMapID(curPlayer, value):
    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ÒÚ
def GetSilver(curPlayer): return curPlayer.GetExAttr6() * ChConfig.Def_PerPointValue + curPlayer.GetSilver()
def SetSilver(curPlayer, totalSilver):
    silver = totalSilver % ChConfig.Def_PerPointValue
    silverPoint = min(totalSilver / ChConfig.Def_PerPointValue, ChConfig.Def_UpperLimit_DWord)
    if silver != curPlayer.GetSilver():
        curPlayer.SetSilver(silver)
    if silverPoint != curPlayer.GetExAttr6():
        curPlayer.SetExAttr6(silverPoint)
    return
##VIPµ½ÆÚʱ¼ä, ÐèҪͬ²½GameServer
def GetVIPExpireTime(curPlayer): return 0
def SetVIPExpireTime(curPlayer, expireTime): return
##×î½üÒ»´ÎÌáÉýVIPµÈ¼¶Ê±¼ä
def GetVIPLVUpTime(curPlayer): return curPlayer.GetExAttr9()
def SetVIPLVUpTime(curPlayer, lvUpTime): return curPlayer.SetExAttr9(lvUpTime, False, True)
##ÁÄÌìÆøÅÝ¿ò
def GetChatBubbleBox(curPlayer): return curPlayer.GetExAttr10()
def SetChatBubbleBox(curPlayer, value): return curPlayer.SetExAttr10(value, False, True)
##ÓÎÏ·³äÖµÖ§¸¶´ú±Ò
def GetPayCoin(curPlayer): return curPlayer.GetExAttr11()
def SetPayCoin(curPlayer, value): return curPlayer.SetExAttr11(min(value, ChConfig.Def_UpperLimit_DWord), False, False)
## »ñÈ¡Åå´÷µÄ³ÆºÅID
def GetTitleID(curPlayer):
    curDienstgradMgr = curPlayer.GetDienstgradManager()
    return curDienstgradMgr.GetCurGradID()
##°éÂÂ
def GetCoupleID(curPlayer):
    coupleInfo = GetCoupleInfo(curPlayer.GetPlayerID())
    return coupleInfo[0] if coupleInfo else 0
def GetCoupleName(curPlayer):
    coupleInfo = GetCoupleInfo(curPlayer.GetPlayerID())
    return coupleInfo[1] if coupleInfo else ""
def GetCoupleJob(curPlayer):
    coupleInfo = GetCoupleInfo(curPlayer.GetPlayerID())
    return coupleInfo[2] if coupleInfo else 1
def GetBridePriceMaxID(curPlayer):
    coupleInfo = GetCoupleInfo(curPlayer.GetPlayerID())
    return coupleInfo[3] if coupleInfo else 0
def GetCoupleInfo(playerID):
    if playerID not in PyGameData.g_coupleInfo:
        return
    return PyGameData.g_coupleInfo[playerID]
def SetCoupleInfo(playerID, coupleInfo):
    if not coupleInfo:
        PyGameData.g_coupleInfo.pop(playerID, None)
    else:
        PyGameData.g_coupleInfo[playerID] = coupleInfo
    return
## Íæ¼ÒËùÊô·þÎñÆ÷×éID
def GetPlayerServerGroupID(curPlayer): return curPlayer.GetExAttr13()
def UpdPlayerServerGroupID(curPlayer):
    # ¸üÐÂ×Ô¼ºµÄ·þÎñÆ÷×éID, ¿ç·þ·þÎñÆ÷²»´¦Àí
    if GameWorld.IsCrossServer():
        return
    serverGroupID = GameWorld.GetServerGroupID()
    if not serverGroupID:
        return
    playerServerGroupID = curPlayer.GetExAttr13()
    if playerServerGroupID != serverGroupID:
        curPlayer.SetExAttr13(serverGroupID, False, True)
        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 GetLingGenMaxIndex(curPlayer):
    return curPlayer.GetExAttr16()
def SetLingGenMaxIndex(curPlayer):
    indexList = [
                    ShareDefine.Def_Effect_Metal, # ½ð
                    ShareDefine.Def_Effect_Wood, # ľ
                    ShareDefine.Def_Effect_Water, # Ë®
                    ShareDefine.Def_Effect_Fire, # »ð
                    ShareDefine.Def_Effect_Earth, # ÍÁ
                ]
    
    
    tempList = [curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AddPointValue % attrID) for attrID in indexList]
    
    curPlayer.SetExAttr16(indexList[tempList.index(max(tempList))])
# ¾³½çÄѶȵȼ¶
def GetRealmDifficulty(curPlayer): return curPlayer.GetExAttr18()
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 - 100
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
##»ñµÃÍæ¼ÒÍþÍûÖµ
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):
    curPlayer.SetFightPower(value % ChConfig.Def_PerPointValue, value / ChConfig.Def_PerPointValue, False) # ²»Í¨ÖªGameServer bNotifyGameServer False
    return
## ÉèÖÃÄ£¿éÕ½¶·Á¦£¬×î´ó20E
def SetMFPFightPower(curPlayer, mfpType, fightPower):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPFightPower % mfpType, min(fightPower, ChConfig.Def_UpperLimit_DWord))
    return
## »ñȡģ¿éÕ½¶·Á¦
def GetMFPFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPFightPower % mfpType)
## ÉèÖÃÄ£¿é¸½¼ÓÕ½¶·Á¦£¬Ö§³Ö³¬¹ý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 GetMFPExFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPExPoint % mfpType) * ChConfig.Def_PerPointValue + \
        curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPEx % mfpType)
#===============================================================================
##»ñÈ¡Íæ¼Ò·ÖÏßÐÅÏ¢
# @param curPlayer Íæ¼ÒʵÀý
# @return Íæ¼Òµ±Ç°·ÖÏßID
# @remarks 
def GetPlayerLineID(curPlayer):
    return curPlayer.GetLineID() + 1
##ÊÓÒ°ÑéÖ¤, Íâ¹ÒÊÓÒ°±äС²»»Ö¸´
# @param curPlayer Íæ¼ÒʵÀý
# @param sight ÊÓÒ°·¶Î§
# @return ÎÞÒâÒå
def SetSight(curPlayer, sight):
    import QuestCommon
    firstMission = QuestCommon.GetCommonMission(curPlayer)
    if firstMission and firstMission.GetProperty(QuestCommon.Def_NewGuyNoSight) == 1:
        curPlayer.SetSight(0)
        return
    
    #Íâ¹ÒºÅ ÊÓÒ°ÑéÖ¤
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        
        if curPlayer.GetSight() > sight:
            curPlayer.SetSight(sight)
        
        return
    
    curPlayer.SetSight(sight)
##»ñÈ¡¹¥»÷¼ä¸ô
# @param curPlayer Íæ¼ÒʵÀý
# @return ¹¥»÷¼ä¸ô
def GetAtkInterval(curPlayer):
    atkInterval = curPlayer.GetAtkInterval()
    
    #Íâ¹ÒºÅ ¹¥»÷¼ä¸ôÑéÖ¤
    if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_AutoCheckHack_State) \
                                      == ChConfig.Def_AutoCheck_State_Danger:
        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 Íæ¼Ò
# @param value Ôö¼ÓÊýÖµ
# @param canOverbrim ¿É·ñÒç³ö(ĬÈϲ»ÐÐ) 
# @param isSysMsg ÊÇ·ñϵͳÌáʾ(ĬÈÏÐèÒª) 
# @return None
def PlayerAddZhenQi(curPlayer, addValue, canOverbrim=False, isSysMsg=True, eventName="unknown", eventData=""):
    if addValue <= 0:
        return True
    
    curZhenQi = GetZhenQi(curPlayer)  # µ±Ç°ÕæÆø
    
    value = curZhenQi + addValue
    
    if value == curZhenQi:
        #ÕæÆøÖµÃ»Óиıä
        return False
    
    #===============================================================================================
    # if isSysMsg:
    #    #GeRen_chenxin_254483:»ñµÃÕæÆøÖµXXµã
    #    NotifyCode(curPlayer, "GeRen_chenxin_254483", [addValue])
    #===============================================================================================
    
    SetZhenQi(curPlayer, value)
    #EventReport.WriteEvent_add_zhenqi(curPlayer, eventName, eventData, addValue, value)
    return True
##Íæ¼Ò¼õÉÙÕæÆø
# @param curPlayer Íæ¼Ò
# @param lostValue ¼õÉÙÊýÖµ
# @return None
def PlayerLostZhenQi(curPlayer, lostValue, eventName="unknown", eventData=""):
    if lostValue <= 0:
        return True
    
    curZhenQi = GetZhenQi(curPlayer)  # µ±Ç°ÕæÆø
    
    value = max(0, curZhenQi - lostValue)
    if value < 0:
        GameWorld.ErrLog("curZhenQi = %s, lostValue = %s" % (curZhenQi, lostValue))
        return False
    
    #GeRen_chenxin_365899:ÏûºÄÕæÆøÖµXXµã.
    #NotifyCode(curPlayer, "GeRen_chenxin_365899", [lostValue])
    
    SetZhenQi(curPlayer, value)
    
    #EventReport.WriteEvent_lost_zhenqi(curPlayer, eventName, eventData, lostValue, value)
    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
#===============================================================================
# #@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)
## ¸ù¾ÝµÈ¼¶»ñµÃÉý¼¶ÐèÒªµÄ×ܾÑé
#  @param playerLv Íæ¼ÒµÈ¼¶
#  @return ·µ»ØÖµ, Éý¼¶ÐèÒªµÄ×ܾÑé
def GetTotalExpByPlayerLv(playerLV):
    lvIpyData = GetPlayerLVIpyData(playerLV)
    if not lvIpyData:
        return 0
    return GetLVUPTotalExpNeed(lvIpyData)
def GetPlayerLVIpyData(playerLV):
    lvIpyData = IpyGameDataPY.GetIpyGameData("PlayerLV", playerLV)
    if not lvIpyData:
        GameWorld.ErrLog("¾Ñé±íÒì³£  lv= %s" % playerLV)
        return
    return lvIpyData
def GetLVUPTotalExpNeed(lvIpyData):
    if not lvIpyData:
        return 0
    return lvIpyData.GetExpPoint() * ChConfig.Def_PerPointValue + lvIpyData.GetExp()
def GetPlayerMaxLV(curPlayer):
    ## »ñÈ¡Íæ¼Òʵ¼Ê¿ÉÉýµÄ×î´óµÈ¼¶
    maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
    curRealmLV = curPlayer.GetOfficialRank()
    realmIpyData = PlayerPrestigeSys.GetRealmIpyData(curRealmLV)
    if not realmIpyData:
        return 0
    playerMaxLV = min(maxLV, realmIpyData.GetNeedLV())
    return playerMaxLV
## »ñµÃÍæ¼Òʵ¼ÊµÈ¼¶
#  @param curPlayer Íæ¼Ò
#  @return Íæ¼Òʵ¼ÊµÈ¼¶
def GetRealPlayerLv(curPlayer):
    #µ±Ç°µÈ¼¶
    realPlayerLv = curPlayer.GetLV()
    #µ±Ç°Íæ¼Ò×ܾÑé
    curTotalExp = GetPlayerTotalExp(curPlayer)
    return GetRealPlayerLvEx(realPlayerLv, curTotalExp)
## »ñµÃÍæ¼Òʵ¼ÊµÈ¼¶
#  @param realPlayerLv µ±Ç°µÈ¼¶
#  @param curTotalExp ×ܾÑé
#  @return Íæ¼Òʵ¼ÊµÈ¼¶
def GetRealPlayerLvEx(realPlayerLv, curTotalExp):
    #Éý¼¶ËùÐè×ܾÑé
    needTotalExp = GetTotalExpByPlayerLv(realPlayerLv)
    if not needTotalExp:
        return realPlayerLv
    
    #Ä£ÄâÉý¼¶,»ñµÃʵ¼ÊµÈ¼¶
    while curTotalExp >= needTotalExp:
        realPlayerLv += 1
        curTotalExp -= needTotalExp
        needTotalExp = GetTotalExpByPlayerLv(realPlayerLv)
        if not needTotalExp:
            break
    return realPlayerLv
## »ñÈ¡Íæ¼Òµ±Ç°×ܾÑé
def GetPlayerTotalExp(curPlayer):
    totalExp = curPlayer.GetTotalExp() # δÂúÒ»¸ö¾ÑéµãµÄ¾Ñ飬·ÇÍæ¼Òʵ¼Ê×ܾÑé
    expPoint = curPlayer.GetExpPoint()
    totalMasterExp = expPoint * ChConfig.Def_PerPointValue + totalExp
    return totalMasterExp
## ÉèÖÃÍæ¼Òµ±Ç°×ܾÑé, ת»¯Îª¾Ñéµã¼°¾Ñé
def SetPlayerTotalExp(curPlayer, totalExp):
    curExp = totalExp % ChConfig.Def_PerPointValue
    expPoint = totalExp / ChConfig.Def_PerPointValue
    
    if curPlayer.GetExpPoint() != expPoint:
        curPlayer.SetExpPoint(expPoint)
    if curPlayer.GetTotalExp() != curExp:
        curPlayer.SetTotalExp(curExp)
    #GameWorld.DebugLog("SetPlayerTotalExp totalExp=%s,expPoint=%s,curExp=%s" 
    #                   % (totalExp, expPoint, curExp), curPlayer.GetPlayerID())
    
    return
#------------------------------------------------------------------------------ 
## ֪ͨѡÖÐÄ¿±ê
#  @param curPlayer: Íæ¼ÒʵÀý
#  @return None
def Sync_SelectObj(curPlayer, objType, objID, isSelect):
    selectObj = ChPyNetSendPack.tagMCNotifySelectObj()
    selectObj.Clear()
    selectObj.Type = objType
    selectObj.ID = objID
    selectObj.isSelect = isSelect
    NetPackCommon.SendFakePack(curPlayer, selectObj)
    return
## ͳ¼ÆÍæ¼ÒÊôÐÔ£¬ÀÛ¼Ó
#  @param attrType ÊôÐÔÀàÐÍ£¬Ð§¹ûID»òÕß×Ö·û´®
#  @param value ÊôÐÔÖµ
#  @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)
    return max(trainRealmLV, curPlayer.GetOfficialRank())
def SetTrainRealmLV(curPlayer, funcType, trainRealmLV):
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TrainRealmLV % funcType, trainRealmLV)
    SyncTrainRealmLV(curPlayer, funcType)
    return
def SyncTrainRealmLV(curPlayer, funcType=None):
    if funcType == None:
        syncFuncTypeList = range(1, 1 + 10)
    else:
        syncFuncTypeList = [funcType]
    infoList = []
    for fType in syncFuncTypeList:
        trainRealmLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TrainRealmLV % fType)
        if not trainRealmLV and funcType == None:
            continue
        lvInfo = ChPyNetSendPack.tagMCTrainRealmLV()
        lvInfo.FuncType = fType
        lvInfo.TrainRealmLV = trainRealmLV
        infoList.append(lvInfo)
    if not infoList:
        return
    clientPack = ChPyNetSendPack.tagMCTrainRealmLVInfo()
    clientPack.InfoList = infoList
    clientPack.Count = len(clientPack.InfoList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
## ÷ÈÁ¦µÈ¼¶
def GetCharmLV(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CharmLV)
def SetCharmLV(curPlayer, charmLV):
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CharmLV, charmLV)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_CharmLV, charmLV)
    return
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
# Áé¸ù - ½ðľˮ»ðÍÁ
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)
#---Íæ¼ÒÀ©Õ¹½Ó¿Ú, Õ½¶·ÊôÐÔ£¬²»´æÊý¾Ý¿â£¬Ö»Í¨Öª±¾ÈË---
##Íæ¼ÒÒÆ¶¯ËÙ¶ÈÖµ, ²»º¬buff¶ÔËٶȵÄÓ°Ï죻 ¹¦ÄܵȶÔËٶȵÄÓ°ÏìÖ±½Ó¸Ä±ä´ËÖµ
def GetSpeedNotBuff(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SpeedValueNotBuff)
def SetSpeedNotBuff(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SpeedValueNotBuff, value)
##Íæ¼ÒÒÆ¶¯ËÙ¶ÈÖµ, º¬buff¶ÔËٶȵÄÓ°Ï죻 ´ËÊýÖµ²»ÊÇÕæÕýµÄÒÆ¶¯ËÙ¶È£¬Ö»ÊÇÓÃÓÚ¼ÆËãÒÆ¶¯ËٶȵIJÎÊýÖµ
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) # ÒÆ¶¯ËÙ¶ÈÖµÔݶ¨¹ã²¥ÖÜÎ§Íæ¼Ò
    
# PVP¹¥»÷»ØÑª
def GetPVPAtkBackHP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PVPAtkBackHP)
def SetPVPAtkBackHP(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PVPAtkBackHP, 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 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 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 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 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
# ÃüÖгɹ¦ÂÊ
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 GetBeHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BeHurtPer)
def SetBeHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BeHurtPer, 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
# ÏÉÃË»ÕÕÂID
def GetFamilyEmblemID(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyEmblemID)
def SetFamilyEmblemID(curPlayer, emblemID): NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyEmblemID, emblemID)
# ÏÉÃËÊÂÎñËٶȼӳÉ
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 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 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)
#---ħ·¨¶ÜÉ˺¦ÎüÊÕÀ¶ºÄ±ÈÂÊ----
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):
    if GameWorld.IsCrossServer():
        curPlayer.SetExAttr4(value, True) # ¿ç·þ·þÎñÆ÷ÐèÒª¹ã²¥ÖÜÎ§Íæ¼Ò
    else:
        curPlayer.SetExAttr4(value)
    
#---×î´ó·À»¤Öµ----
def GetMaxProDef(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrMaxProDef)
def SetMaxProDef(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrMaxProDef, value)
    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_MaxProDef, value) # ÖÜÎ§Íæ¼ÒÐèҪ֪ͨ
    
#---ÉúÃüÉÏÏÞ»»ËãΪ·À»¤ÖµµÄ°Ù·Ö±È----
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)
# ÿ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 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)
# ¼õÉÙÖ¸¶¨¼¼ÄÜ×éCD XX%
def GetTheFBSkillsCD(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TheFBSkillsCD)
def SetTheFBSkillsCD(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_TheFBSkillsCD, value)
# ׯÉչ̶¨É˺¦
def GetBurnValue(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BurnValue)
def SetBurnValue(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BurnValue, value)
# ÑÓ³¤×ÆÉÕʱ¼ä°Ù·Ö±È
def GetBurnTimePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BurnTimePer)
def SetBurnTimePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BurnTimePer, value)
# ¼õÒÆ¶¯ËٶȰٷֱÈ
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 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):
    ## »ñÈ¡¹¦ÄܵãÔ¤ÏȼÆËãµÄËù¼ÓÊôÐÔÖµ
    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
#-------------------------------------------------------------------------------
## ÉèÖÃÍæ¼Ò×ÖµäÖµ, ´æ¿â
def NomalDictSetProperty(curPlayer, key, value, dType=0):
    if CrossPlayerData.IsNeedProcessCrossPlayer(curPlayer) and key not in \
        [ChConfig.Def_PDict_FightPower_Total, ChConfig.Def_PDict_FightPower_TotalEx, ChConfig.Def_PlayerKey_CrossRegisterMap]:
        playerID = curPlayer.GetPlayerID()
        changeDict = PyGameData.g_crossPlayerDictChangeInfo.get(playerID, {})
        changeDict[(key, dType)] = value
        PyGameData.g_crossPlayerDictChangeInfo[playerID] = changeDict
        
    if value == 0:
        curPlayer.NomalDictDelProperty(key, dType)
        return
    # 2^31 - 1
    curPlayer.NomalDictAddProperty(key, min(value, ChConfig.Def_UpperLimit_DWordEx), dType)
    return
## ֪ͨף¸£Öµ
def Sync_BlessValue(curPlayer, blessType, value, multiple=0):
    itemList = []
    valuePack = ChPyNetSendPack.tagMCSyncSingleBlessValue()
    valuePack.Clear()
    valuePack.Type = blessType
    valuePack.Value = value
    valuePack.Multiple = multiple
    itemList.append(valuePack)
    
    sendPack = ChPyNetSendPack.tagMCSyncBlessValue()
    sendPack.Clear()
    sendPack.TypeCnt = len(itemList)
    sendPack.BlessInfo = itemList
    
    #֪ͨ¿Í»§¶Ë
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
#ͬ²½ÉèÖÃ Íæ¼ÒºÍ³èÎï¼°ÒÑÕÙ»½µÄÕÙ»½ÊÞ ÊÓÒ°²ã
def SetPlayerSightLevel(curPlayer, sightLevel):
    # µ±ÊÓÒ°ÉèÖÃ0ʱ£¬ÔÚ¾³½çµØÍ¼Ôò×Ô¶¯ÉèÖÃÒÑÑ¡ÔñµÄ¾³½çÄѶÈÊÓÒ°
    if sightLevel == 0:
        realmDifficulty = GetMapRealmDifficulty(curPlayer)
        if realmDifficulty:
            sightLevel = realmDifficulty
            GameWorld.DebugLog("¾³½çµØÍ¼×Ô¶¯ÉèÖÃÒÑÑ¡ÔñµÄ¾³½çÄѶÈÊÓÒ°: sightLevel=%s" % sightLevel)
            
    mapSightType = GameMap.GetMapSightType()
    if mapSightType == ChConfig.SightType_Private:
        sightLevel = curPlayer.GetPlayerID() # Ç¿ÖÆÎªË½Óв㼶
        
    curPlayer.SetSightLevel(sightLevel)
    rolePet = curPlayer.GetPetMgr().GetFightPet()
    #ÎÞ³öÕ½³èÎï
    if rolePet:
        rolePet.SetSightLevel(sightLevel)
    
    for i in range(curPlayer.GetSummonCount()):
        curSummon = curPlayer.GetSummonNPCAt(i)
        if not curSummon:
            continue
        curSummon.SetSightLevel(sightLevel)
    return
def SetPlayerSightLevelByMap(curPlayer):
    playerID = curPlayer.GetPlayerID()
    sightLevel = playerSightLevel = curPlayer.GetSightLevel()
    mapSightType = GameMap.GetMapSightType()
    if mapSightType == ChConfig.SightType_Private:
        sightLevel = playerID
    else:
        # ĬÈϹ«¹²ÊÓÒ° ChConfig.SightType_Public
        if playerSightLevel == playerID:
            sightLevel = 0 # ˽ÈËÊÓÒ°Ç¿ÖÆ¸ÄΪ¹«¹²ÊÓÒ°
        else:
            # ¹«¹²ÊÓÒ°×ñÑÆäËû×Ô¶¨ÒåÊÓÒ°²ã¼¶Âß¼
            return
    
    if sightLevel == playerSightLevel:
        return
    GameWorld.DebugLog("µØÍ¼Çл»Íæ¼ÒÊÓÒ°: mapSightType=%s,playerSightLevel=%s to sightLevel=%s" 
                       % (mapSightType, playerSightLevel, sightLevel), playerID)
    SetPlayerSightLevel(curPlayer, sightLevel)
    return