#!/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 ChItem
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 PlayerWing
import PlayerExpandPackCfgMgr
import PlayerWorldAverageLv
import GameLogic_ManorWar
import PlayerActivity
import HighLadderTube
import FBCommon
import PlayerViewCacheTube
import PassiveBuffEffMng
import PlayerGameEvent
import EventReport
import PlayerTeHui
import GameLogic_XMZZ
import PlayerSuccess
import PlayerPet
import PlayerGreatMaster
import ItemControler
import GameFuncComm
import PlayerMergeEvent
import IpyGameDataPY
import PlayerRune
import GameLogic_DuJie
import PyGameData
import PlayerMagicWeapon
import GameLogic_SealDemon
import PlayerTJG
import PlayerVip
import PlayerRefineStove
import PlayerFamilyTech
import PlayerCostRebate
import PlayerFairyCeremony
import ChNetSendPack
import PlayerState
import QuestCommon
import GMShell
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 abs(gameWorldTick - clientWorldTick) >= Def_Max_Move_Tick:
        #ʱ¼äÏà²î¹ý´ó£¬¿ÉÄÜÒòÍøÂçÒýÆð£¬À»Ø
        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 = random.choice((10, 10, 15, 15, 20, 25, 30, 50))
    #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=[]):
    # Èç¹ûÊÇ¿ç·þ·þÎñÆ÷£¬Ôò¹ã²¥×Ó·þ
    if GameWorld.IsMergeServer():
        sendMsg = str([country, msgMark, msgParamList, lineID, mergeMinOSD, mergeMaxOSD, mergeMapInfo])
        GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'MergeWorldNotify',
                                                                  sendMsg, len(sendMsg))
        FBNotify(msgMark, msgParamList) # ¿ç·þÖеÄÈ«·þ¹ã²¥Ö»ÔÚµØÍ¼ÖÐ×ö¹ã²¥¼´¿É£¬·ÀÖ¹²»Í¬¿ç·þ·ÖÇøµÄµØÍ¼»áÏ໥¿´µ½¹ã²¥£¬ÌåÑé²»ºÃ
    else:
        GameWorld.GetPlayerManager().BroadcastCountry_NotifyCode(country, 0, msgMark,
                                                        __GetNotifyCodeList(msgParamList), lineID)
    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=[]):
    '''ÅúÁ¿·¢ËÍÓʼþ, ÓÃÓÚ˲¼äÐèÒª·¢ËͶà·â£¨´óÁ¿£©ÓʼþµÄ£¬±ÈÈçһЩ¹«¹²¸±±¾»î¶¯µÈ½áËãʱ
    @param mailTypeKey: ÓʼþÄ£°åkey
    @param batchPlayerIDList: [playerIDList, playerIDList, ...]
    @param batchAddItemList: [addItemList, addItemList, ...]
    @param batchParamList: [paramList, paramList, ...]
    @param batchGold: [batchGold, batchGold, ...]
    @param batchGold: [batchGoldPaper, batchGoldPaper, ...]
    @param batchGold: [batchSilver, batchSilver, ...]
    '''
    msgInfo = str([mailTypeKey, batchPlayerIDList, batchAddItemList, batchParamList, batchGold, batchGoldPaper, batchSilver])
    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):
    if not mailTypeKey:
        mailTypeKey = ShareDefine.DefaultLackSpaceMailType
    
    content = "%s%s" % (mailTypeKey, json.dumps(paramList, ensure_ascii=False))
    SendMail("", content, 30, playerIDList, addItemList, gold, goldPaper, silver)
    return
## ¹¦ÄÜ·¢·ÅÎïÆ·²¹³¥/½±ÀøÓʼþ
#  @param addItemList [(itemID, itemCnt, isBind), {»òÎïÆ·ÐÅÏ¢×Öµä}, ...]
#  @return
def SendMail(title, content, getDays, playerIDList, addItemList, gold=0, goldPaper=0, silver=0):
    if not playerIDList:
        return
    
#    if not addItemList:
#        return
    
    # ÓÐЧÌìÊýÏÞÖÆ
    if getDays <= 0:
        return
    
    # ¿ç·þ·þÎñÆ÷²»ÔÊÐí·¢ËÍÓʼþ
    if GameWorld.IsMergeServer():
        return
    
    itemCountDict = {}
    combineItemList = [] # ºÏ²¢ºóµÄÎïÆ·Áбí
    for mailItem in addItemList:
        if isinstance(mailItem, dict):
            combineItemList.append(mailItem)
            continue
        
        if len(mailItem) != 3:
            continue
        
        itemID, itemCnt, isBind = mailItem
        
        if ItemControler.GetAppointItemRealID(itemID):
            # ¶¨ÖÆÎïÆ·×ª»¯ÎªÎïÆ·ÐÅÏ¢×Öµä
            appointItemObj = ItemControler.GetItemByData(ItemControler.GetAppointItemDictData(itemID, isBind))
            if not appointItemObj:
                GameWorld.ErrLog("Óʼþ¶¨ÖÆÎïÆ·×ª»¯Ê§°Ü£¡itemID, itemCnt, isBind" % (itemID, itemCnt, isBind))
                continue
            combineItemList.append(ItemCommon.GetMailItemDict(appointItemObj))
            appointItemObj.Clear()
        else:
            key = (itemID, isBind)
            itemCountDict[key] = itemCountDict.get(key, 0) + itemCnt
            
    for key, itemCnt in itemCountDict.items():
        itemID, isBind = key
        combineItemList.append((itemID, itemCnt, isBind))
    cmdList = [title, content, getDays, playerIDList, combineItemList, gold, goldPaper, silver]
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "SendMail", '%s' % (cmdList), len(str(cmdList)))
    return True
## ¹¹½¨ÏµÍ³Ìáʾ²ÎÊýÁбí
#  @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 curPlayer.GetHP() <= 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
    
    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
    
    if curNPC.GetNPCID() not in ReadChConfig.GetEvalChConfig('BreakPlayerCollectNPCIDList'):
        return
    
    GameWorld.DebugLog('    ²É¼¯±»´ò¶Ï ²É¼¯ÎïNPCID=%s' % curNPC.GetNPCID())
    #È¡Ïû²É¼¯×´Ì¬
    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)
    
    # ½áÊø°Ú̯/²é¿´°Ú̯
    EventShell.ExitShopItem(curPlayer)
    EventShell.ExitWatchShopItem(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)
        
    GameLogic_ManorWar.DoExitFB(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)
    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):
    return
    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СʱµÄÇëµ÷Õû³¬Ê±ÏÞÖÆ
    # ×¢: ·µ»ØÖµÎªNoneʱ£¬Ö»ÄÜ´ú±íÍæ¼Ò²»ÊÇÔÚ±¾µØÍ¼ÀëÏß1СʱÄÚ£¬²¢²»ÄÜ´ú±íÍæ¼Òµ±Ç°ÊÇ·ñÔÚÏß״̬£¬¿ÉÄÜÔÚÆäËûµØÍ¼
    if playerID not in PyGameData.g_disconnectPlayer:
        return
    return PyGameData.g_disconnectPlayer[playerID][0]
def GetPlayerLeaveServerPos(playerID):
    # »ñÈ¡Íæ¼Ò´Ó±¾µØÍ¼ÖÐÀëÏßʱµÄ×ø±ê
    if playerID not in PyGameData.g_disconnectPlayer:
        return
    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)
    
    # Èç¹ûÔÚ°Ú̯ÖУ¬Ìáʾ°Ú̯¹Ø±Õ
    playerShop = curPlayer.GetPlayerShop()
    if playerShop.GetIsStartShop():
        NotifyCode(curPlayer, "GeRen_admin_70569")
    
    #À뿪µØÍ¼·þÎñÆ÷
    __PlayerLeaveServerLogic(curPlayer, tick, False)
    
    FBLogic.DoPlayerChangeMapLogic(curPlayer, tick)
    #summonList = list()
    
    #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
        
    
    #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
    
    #À뿪¸±±¾
    mapID = curPlayer.GetFromMapID()
    posX = curPlayer.GetFromPosX()
    posY = curPlayer.GetFromPosY()
    
    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 GameWorld.GetMap().GetAutoSize() and GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount() == 1:
        #Èç¹û¸±±¾ÖÐÖ»ÓÐÕâÒ»¸öÈË, ÄÇô°ÑÕâ¸ö¸±±¾ÉèÖÃÎªÍæ¼Ò°²È«ÏÂÏß, ¹Ø±Õ¸±±¾
        gameFB = GameWorld.GetGameFB()
        gameFB.SetIsSafeClose(1)
    
    #===============================================================================================
    # #Èç¹ûÍæ¼ÒÊÇËÀÍö״̬£¬ÔòÏȸ´»î£¬ÊÖÓβ߻®²»Ï븴»îÍ˳ö
    # if curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
    #    curPlayer.Reborn(ChConfig.rebornType_System)
    #    curPlayer.SetHP(curPlayer.GetMaxHP())
    #    ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
    #===============================================================================================
    
    PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, curPlayer.GetFromLineID())
    
    #ÔÚ¿ÕÏлòÕßÒÆ¶¯×´Ì¬ÏÂ,²ÅÄÜËøËÀÍæ¼Ò
    if curPlayer.GetPlayerAction() in [IPY_GameWorld.paNull] or curPlayer.IsMoving():
        #°ÑÍæ¼ÒËøËÀ
        curPlayer.BeginEvent()
    
    return
#---------------------------------------------------------------------
def ResetMergeFBPlayerCntInfo(resetMapID):
    # ÖØÖÿç·þ»î¶¯¸±±¾µØÍ¼ÈËÊý·ÖÅäÇé¿öÐÅÏ¢
    mapID = GameWorld.GetMap().GetMapID()
    if mapID != ChConfig.Def_MergeTransMapID:
        return
    GameWorld.Log("ÖØÖÿç·þ»î¶¯¸±±¾µØÍ¼ÈËÊý·ÖÅäÇé¿öÐÅÏ¢: resetMapID=%s" % resetMapID)
    gameWorld = GameWorld.GetGameWorld()
    mergeFBPlayerCntDict = ReadChConfig.GetEvalChConfig("MergeFBPlayerCount")
    for reqMapID, mapInfo in mergeFBPlayerCntDict.items():
        if resetMapID and resetMapID != reqMapID:
            continue
        for playerMapID in mapInfo[1]:
            playerCnt = gameWorld.GetGameWorldDictByKey(ChConfig.Map_WorldKey_MergeFBMapPlayerCnt % playerMapID)
            for num in xrange(1, 1 + playerCnt):
                playerID = gameWorld.GetGameWorldDictByKey(ChConfig.Map_WorldKey_MergeFBMapPlayerID % (playerMapID, num))
                gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBMapPlayerID % (playerMapID, num), 0) # ÖØÖöÔÓ¦µÄÍæ¼ÒID
                gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBPlayerMapID % (reqMapID, playerID), 0) # ÖØÖÃÍæ¼ÒID¶ÔÓ¦µÄµØÍ¼
            gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBMapPlayerCnt % playerMapID, 0) # ÖØÖõØÍ¼ÈËÊý
    return
def __GetMergeFBPlayerMapID(curPlayer, reqMapID):
    # »ñÈ¡Íæ¼ÒËù·ÖÅäµÄ¿ç·þ»î¶¯µØÍ¼ID
    # @param reqMapID: ¿ÉÒÔÊDZ¾·þ»î¶¯µÄµØÍ¼ID±êʶ£» Ò²¿ÉÒÔÊÇÖ¸¶¨µÄ¿ç·þ»î¶¯µØÍ¼ID, Èç¹ûÊÇÖ¸¶¨µÄµØÍ¼IDÒ²ÊÇÖ±½Ó·µ»Ø
    
    mergeFBPlayerCntDict = ReadChConfig.GetEvalChConfig("MergeFBPlayerCount")
    if reqMapID not in mergeFBPlayerCntDict:
        return reqMapID
    
    playerID = curPlayer.GetPlayerID()
    gameWorld = GameWorld.GetGameWorld()
    
    playerMapID = gameWorld.GetGameWorldDictByKey(ChConfig.Map_WorldKey_MergeFBPlayerMapID % (reqMapID, playerID))
    if playerMapID:
        GameWorld.DebugLog("ÒѾÓзÖÅä¿ç·þ»î¶¯µØÍ¼£¬Ö±½Ó·µ»Ø£¡playerMapID=%s" % (playerMapID), playerID)
        return playerMapID
    
    # »¹Ã»·ÖÅä¸ÃÍæ¼Ò£¬ Ôò¿ªÊ¼Ñ¡Ôñ·ÖÅäµÄµØÍ¼ID
    maxPlayerCnt, mapIDList = mergeFBPlayerCntDict[reqMapID]
    minPlayerCount = 0 # ×îÉٵĵØÍ¼Íæ¼ÒÈËÊý
    minPlayerMapID = 0 # ×îÉÙÈËÊýµÄµØÍ¼ID
    for mID in mapIDList:
        curMapPlayerCnt = gameWorld.GetGameWorldDictByKey(ChConfig.Map_WorldKey_MergeFBMapPlayerCnt % mID)
        if curMapPlayerCnt < maxPlayerCnt:
            playerMapID = mID
            break
        
        # ±£´æ×îÉÙÈËÊýµÄµØÍ¼IDÐÅÏ¢
        if not minPlayerCount or (minPlayerCount and curMapPlayerCnt < minPlayerCount):
            minPlayerCount = curMapPlayerCnt
            minPlayerMapID = mID
    
    # Èç¹ûûÓÐÈËÊýδÂúµÄ»î¶¯µØÍ¼£¬Ôò·ÖÅäµ½ÈËÊý½ÏÉٵĵØÍ¼
    if not playerMapID:
        playerMapID = minPlayerMapID
        
    # ¸üзÖÅäÐÅÏ¢
    if playerMapID:
        mapPlayerCnt = gameWorld.GetGameWorldDictByKey(ChConfig.Map_WorldKey_MergeFBMapPlayerCnt % playerMapID) + 1
        gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBMapPlayerCnt % playerMapID, mapPlayerCnt)
        gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBMapPlayerID % (playerMapID, mapPlayerCnt), playerID)
        gameWorld.SetGameWorldDict(ChConfig.Map_WorldKey_MergeFBPlayerMapID % (reqMapID, playerID), playerMapID)
        GameWorld.Log("·ÖÅä¿ç·þ»î¶¯Íæ¼ÒËùÊôµØÍ¼: plaeyrID=%s,reqMapID=%s,·ÖÅäMapID=%s,mapPlayerCnt=%s" 
                      % (playerID, reqMapID, playerMapID, mapPlayerCnt))
        
    return playerMapID
##Íæ¼Ò½øÈ븱±¾
# @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.IsMergeServer():
        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:
                PlayerResetWorldPosFB(curPlayer, mapID, posX, posY, False, fbID, funcLineID=lineID)
                return
            else:
                bossID = GameLogic_SealDemon.CurFBLineBOSSID(lineID)
                extendParamList = [bossID]
        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 curPlayer.GetHP() <= 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 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 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
        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):
    '''
    ²ÎÊý˵Ã÷:
        @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())
    curPlayer.ResetWorldPosReq(sceneMapID, posX, posY, takeTruck, fbID, msg)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ChangeMapID, sceneMapID)
    
    #ÇеØÍ¼´¦ÀíÍæ¼ÒʱÖÓ¾ÀÕýÎÊÌ⣨ÐèҪһֱͨ¹ýÍæ¼ÒʱÖÓ¼ÆËãµÄ£©
    RefreshPlayerTick(curPlayer)
    NotifyPrepareChangeMap(curPlayer, sceneMapID, funcLineID)
    return
# ֪ͨ׼±¸Çл»µØÍ¼
def NotifyPrepareChangeMap(curPlayer, sceneMapID, funcLineID):
    curPlayer.SetVisible(False)
    sendPack = ChPyNetSendPack.tagMCPrepareChangeMap()
    sendPack.Clear()
    sendPack.MapID = sceneMapID
    sendPack.FuncLineID = funcLineID
    
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
# ֪ͨ¿ªÊ¼Çл»µØÍ¼
def NotifyStartChangeMap(curPlayer):
    GameWorld.DebugLog("֪ͨ¿ªÊ¼Çл»µØÍ¼, NotifyStartChangeMap")
    sendPack = ChPyNetSendPack.tagMCStartChangeMap()
    sendPack.Clear()
    sendPack.MapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeMapID)
    sendPack.FuncLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqFBFuncLine)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    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 curPlayer.GetHP() <= 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):
        #ÖØÖÃ×ø±ê
        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 curMapID not in PyGameData.g_commMapLinePlayerCountDict or tagMapID not in PyGameData.g_commMapLinePlayerCountDict:
        return tagLineID
    tagLinePlayerCountDict = PyGameData.g_commMapLinePlayerCountDict[tagMapID]
    
    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, 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
    
    # ¿ÉÒÔÓÃÀ´³£¹æ·ÖÁ÷µÄÏß·ÈËÊý×ÖµäÐÅÏ¢, ²¢²»ÊÇËùÓÐÏß·¶¼¿ÉÒÔÓÃÀ´×öÈËÊý·ÖÁ÷µÄ£¬±ÈÈçÖÐÁ¢µØÍ¼ÓжàÌõÏßÓÃÀ´·ÖÁ÷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, mapID, npcID, lineIDList):
    '''»ñȡĿ±êµØÍ¼boss·ÖÁ÷Ïß·
    ¸ù¾ÝÈËÊý·ÖÁ÷Íæ¼Ò£¬bossËÀÍö״̬£¬Ö»ÄÜ·ÖÁ÷µ½ÒÑËÀÍöÏß·
    ¶ÓÎéÎÞÊÓÈκιæÔò£¬Ä¬ÈÏ·ÖÅäµ½¶ÓÎé¶ÓÔ±¶àµÄÄÇÌõÏß
    '''
    playerID = curPlayer.GetPlayerID()
    playerTeamID = curPlayer.GetTeamID()
    
    hurtTeamLineID = -1
    hurtTeamMemCount = -1
    
    emptyLineID = -1
    bossLinePlayerCntList = []
    
    deadLineList = PyGameData.g_bossShuntDeadLine.get(npcID, [])
    bossState = not deadLineList # boss¹«¹²×´Ì¬, Ö»ÒªÓÐÒ»ÌõÏß·ÊÇËÀÍöµÄ¾ÍÊÇËÀÍö
    
    GameWorld.DebugLog("Íæ¼Òboss·ÖÁ÷: playerTeamID=%s,mapID=%s,npcID=%s,lineIDList=%s,bossState=%s,deadLineList=%s,g_bossShuntPlayerInfo=%s" 
                       % (playerTeamID, mapID, npcID, lineIDList, bossState, deadLineList, PyGameData.g_bossShuntPlayerInfo), playerID)
    
    for lineID in lineIDList:
        key = (mapID, lineID)
        shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
        playerCount = 0
        teamPlayerCount = 0
        for shuntInfo in shuntPlayerDict.values():
            bossID = shuntInfo[0]
            if npcID != bossID:
                continue
            playerCount += 1
            shuntTeamID = shuntInfo[1]
            if playerTeamID and playerTeamID == shuntTeamID:
                teamPlayerCount += 1
        
        if teamPlayerCount and teamPlayerCount > hurtTeamMemCount:
            hurtTeamMemCount = teamPlayerCount
            hurtTeamLineID = lineID
            
        lineBossState = lineID not in deadLineList # µ±Ç°Ïß·boss״̬
        if bossState != lineBossState:
            GameWorld.DebugLog("    lineID=%s,lineBossState=%s != bossState=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" 
                           % (lineID, lineBossState, bossState, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
            continue
        
        GameWorld.DebugLog("    lineID=%s,lineBossState=%s,playerCount=%s,teamPlayerCount=%s,hurtTeamMemCount=%s,hurtTeamLineID=%s" 
                           % (lineID, lineBossState, playerCount, teamPlayerCount, hurtTeamMemCount, hurtTeamLineID), playerID)
        
        if not playerCount:
            if emptyLineID < 0:
                emptyLineID = lineID
        else:
            bossLinePlayerCntList.append([playerCount, lineID])
            
    if hurtTeamLineID >= 0:
        GameWorld.DebugLog("    ·ÖÁ÷µ½¶ÓÓÑÈËÊý¶àµÄÏß· hurtTeamLineID=%s" % hurtTeamLineID, playerID)
        return hurtTeamLineID
    
    if not bossLinePlayerCntList:
        GameWorld.DebugLog("    ûÓÐÈËÔÚ¸Ãboss״̬ϵÄÏß·£¬Ä¬ÈÏ¿ÕÐÂÏß·!bossState=%s,emptyLineID=%s" % (bossState, emptyLineID), playerID)
        return emptyLineID
    
    bossLinePlayerCntList.sort() # ÉýÐò
    playerCount, minPlayerCntLineID = bossLinePlayerCntList[0]
    bossShuntPlayerCountMax = IpyGameDataPY.GetFuncCfg("BossShunt", 2)
    if playerCount >= bossShuntPlayerCountMax and emptyLineID >= 0:
        GameWorld.DebugLog("    ·ÖÁ÷µ½¿ÕÐÂÏß· bossState=%s,emptyLineID=%s" % (bossState, emptyLineID), playerID)
        return emptyLineID
    
    GameWorld.DebugLog("    ·ÖÁ÷µ½ÈËÊý×îÉÙµÄÏß· bossState=%s,minPlayerCntLineID=%s,bossLinePlayerCntList=%s" 
                       % (bossState, minPlayerCntLineID, bossLinePlayerCntList), 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 curTeamPlayer.GetHP() <= 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 moneyType »õ±ÒÀàÐÍ 1±íʾ½ð×Ó£¬2±íʾ½ðƱ£¬3±íÊ¾Òø×Ó£¬4±íÊ¾ÒøÆ±, 5:½ð×Ó/½ðƱ 6:Òø×Ó/񿮱
# @return ·µ»ØÖµ, »õ±ÒÀàÐÍ
# @remarks ת±ä¸¶·Ñ»õ±ÒÀàÐÍ 
def ChangeMoneyType(curPlayer, moneyType):
#    if moneyType == 5:
#        return curPlayer.GetUseGoldType()
#    
#    if moneyType == 6:
#        return curPlayer.GetUseSilverType()
    if moneyType not in ChConfig.Def_MoneyType_All:
        GameWorld.ErrLog("½ðÇ®ÀàÐÍÌîд´íÎó %s" % moneyType)
        
    return moneyType
#---------------------------------------------------------------------
##»ñÈ¡Íæ¼Ò»õ±ÒÊý
# @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 in ShareDefine.TYPE_Price_CurrencyDict:
        return GetPlayerCurrency(curPlayer, TYPE_Price)
    
    return 0
## »ñÈ¡Íæ¼Ò²Ö¿â½ðÇ®Êý
#  @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)
    curPlayer.SendPropertyRefresh(refreshType, value, False)
    return
# Í¨ÖªÍæ¼ÒËùÓÐ×Ô¶¨Òå»õ±Ò
def NotifyPlayerAllCurrency(curPlayer):
    notifyList = []
    for currencyType in ShareDefine.TYPE_Price_CurrencyDict:
        refreshType = ShareDefine.TYPE_Price_CurrencyDict[currencyType]
        if refreshType == None:
            # ²»ÐèҪ֪ͨ¿Í»§¶Ë
            continue
        
        #´Ë´¦¸ù¾ÝÐèÇóÈôValueΪ0 ¿É²»Í¨Öª¿Í»§¶Ë£¬¾ßÌ幦ÄÜÖÆ×÷Õß¾ö¶¨
        notifyStruct = ChPyNetSendPack.tagRefreshType()
        notifyStruct.RefreshType = refreshType
        notifyStruct.Value = GetPlayerCurrency(curPlayer, currencyType)
        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)
##Íæ¼ÒÊÇ·ñÓÐÇ®¿î
# @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 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:
        if needNotify and notifyCode:
            NotifyCode(curPlayer, notifyCode)
        return False
    
    return True
#---------------------------------------------------------------------
##Íæ¼ÒÊÇ·ñÓÐÇ®¿î
# @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 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 ,ÊýÁ¿
# @return ·µ»ØÖµÕæ, ¸¶¿î³É¹¦
# @remarks Íæ¼Ò¸¶¿î
def PayMoney(curPlayer, type_Price, price, costType=ChConfig.Def_Cost_Unknown, infoDict={}, quantity=1, costVIPGold= -1, isNotify=True):
    if price == 0:
        return True
    if price < 0:
        GameWorld.Log('###---¿ÛÇ®Òì³£ = %s' % (price), curPlayer.GetPlayerID())
        return False
    
    #½ð×ÓÖ§¸¶
    if type_Price == IPY_GameWorld.TYPE_Price_Gold_Money:
        curPlayerGold = curPlayer.GetGold()
        if curPlayerGold < price:
            NotifyCode(curPlayer, "GoldErr")
            return False
        updPlayerGold = curPlayerGold - price
        curPlayer.SetGold(updPlayerGold)
        
        curBourseMoney = GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
        updBourseMoney = curBourseMoney
        #µ±Êǽ»Ò×Ëù¿Û·Ñʱ£¬Ôò±Ø¶¨¿Û³ý½»Ò×¶î¶È
        if costType == ChConfig.Def_Cost_BourseBuy:
            updBourseMoney = max(0, curBourseMoney - price)
        #ÆäËûÈç¹ûµ±Ç°½ð×ӱȽ»Ò×¶î¶È»¹ÉÙ£¬ÔòÇ¿ÖÆµ÷Õû½»Ò×¶î¶ÈΪµ±Ç°½ð×ÓÊý(ÕâÖÖÇé¿öÒ»°ãÊǷǽ»Ò×ËùÏû·ÑµÄ£¬ÐèҪͬ²½¿Û³ý½»Ò×Ëù¿É¹ºÂò¶î¶È)
        elif updPlayerGold < updBourseMoney:
            updBourseMoney = updPlayerGold
        if updBourseMoney != curBourseMoney:
            SetPlayerCurrency(curPlayer, ShareDefine.TYPE_Price_BourseMoney, updBourseMoney)
        infoDict["BourseMoney"] = updBourseMoney
        
    #½ðƱ֧¸¶
    elif type_Price == IPY_GameWorld.TYPE_Price_Gold_Paper:
        curPlayerGoldPaper = curPlayer.GetGoldPaper()
        if curPlayerGoldPaper < price:
            NotifyCode(curPlayer, "GoldPaperErr")
            return False
        curPlayer.SetGoldPaper(curPlayerGoldPaper - price)
       
    #Òø×ÓÖ§¸¶
    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 in ShareDefine.TYPE_Price_CurrencyDict:
        curCurrency = GetPlayerCurrency(curPlayer, type_Price)
        if curCurrency < price:
            return False
        #ÓÐ×ã¹»µÄǮ֧¸¶
        SetPlayerCurrency(curPlayer, type_Price, curCurrency - price)
    else:
        GameWorld.Log("¸¶·Ñ½ðÇ®Òì³£ type_Price = %s" % (type_Price), curPlayer.GetPlayerID())
        return False   
    
    #Ìí¼Ó¿ç·þ²Ù×÷ʼþ
    if costType in ChConfig.MergeServerCanCostType:
        eventInfo = [type_Price, price, costType, infoDict, quantity, costVIPGold]
        PlayerMergeEvent.AddMSPlayerEvent(curPlayer.GetPlayerID(), PlayerMergeEvent.Def_MSPEvent_PayMoney, eventInfo)
    
    #¸¶¿îÒÔºóºóÐø²Ù×÷
    __PayMoneyAfter(curPlayer, type_Price, price, costType, infoDict, quantity, costVIPGold)
    
    #֪ͨ¿Í»§¶Ëʧȥ½ðÇ®
    if isNotify:
        NotifyCode(curPlayer, "LostMoney", [type_Price, price])
    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 == IPY_GameWorld.TYPE_Price_Gold_Money:
        __PayMoneyAfterByGoldMoney(curPlayer, 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)
    
    #»îÔ¾¶È´¦Àí
    PlayerActivity.OnPayMoneyActivity(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] \
        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 == 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, price, costType, infoDict, costVIPGold):
        
    
    # ³äÖµ»î¶¯Íæ¼ÒÏûºÄÔª±¦´¦Àí
    #PlayerGoldAction.PlayerUseGold(curPlayer, price)
    
    # Ïû·Ñ·µÀû
    PlayerCostRebate.AddCostRebateGold(curPlayer, costType, price, infoDict)
    # ¾ø°æ½µÁÙ
    PlayerFairyCeremony.AddFCCostGold(curPlayer, costType, price)
    # Ïû·ÑVIP
#    if costVIPGold < 0:
#        costVIPGold = price
    #PlayerCostVIP.AddCostVIPExp(curPlayer, costType, costVIPGold)
    
    # ʼþ»ã±¨
    #===========================================================================
    # 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 priceType == IPY_GameWorld.TYPE_Price_Gold_Money:
        if curPlayer.GetGold() + value > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return
        
        curPlayer.SetGold(curPlayer.GetGold() + value)
        
        if isGiveBourseMoney:
            GiveMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney, value)
            addDataDict["BourseMoney"] = GetMoney(curPlayer, ShareDefine.TYPE_Price_BourseMoney)
            
    elif priceType == IPY_GameWorld.TYPE_Price_Gold_Paper:
        if curPlayer.GetGoldPaper() + value > ChConfig.Def_PlayerTotalMoney_Gold:
            #³¬¹ý½ðÇ®ÉÏÏÞ
            NotifyCode(curPlayer, "MoneyIsFull", [priceType])
            return
        
        curPlayer.SetGoldPaper(curPlayer.GetGoldPaper() + value)
        
    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 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.Log("½ðÇ®ÀàÐÍ´íÎó, priceType = %s" % (priceType), curPlayer.GetPlayerID())
        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»¼Ç¼
    if priceType not in [IPY_GameWorld.TYPE_Price_Gold_Money, IPY_GameWorld.TYPE_Price_Gold_Paper] \
        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)
#===============================================================================
#    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 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()
    curReinCnt = curPlayer.GetReincarnationLv() # µ±Ç°×ªÉú´ÎÊý
    
    addPointList = IpyGameDataPY.GetFuncEvalCfg("LVUPAddPoint", 1)
    
    addPoint = addPointList[-1] if curReinCnt >= len(addPointList) else addPointList[curReinCnt]
    
    if addPoint == None:
        raise Exception('Íæ¼Ò»ñµÃÉý¼¶ÊôÐÔµãÒì³£, reincarnationLv = %s PlayerID = %s' % (curReinCnt, curPlayerID))
        return
    
    return int(addPoint)
#---------------------------------------------------------------------
## ¹¦ÄÜÄ£¿éÕ½¶·Á¦Àà
#
#  ·ÖÄ£¿é¼ÆËãÕ½¶·Á¦
class ModuleFightPower():
    
    __AttrName = "%s" # ²ÎÊýΪChConfig.Def_Calc_AllAttrType_MAX¶ÔÓ¦ËùÓÐÊôÐÔÁбíË÷Òý
    
    ## ³õʼ»¯
    #  @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
#            if attrIndex == ChConfig.TYPE_Calc_SuperHit:
#                value = ChConfig.Def_SuperHitPercent # ĬÈÏ×îµÍ±©»÷±¶Öµ
            setattr(self, self.__AttrName % attrIndex, value)
        return
            
    ## ¸ù¾ÝÕ½¶·ÊôÐÔÁбíÉèÖüÆËãÕ½¶·Á¦ÊôÐÔ
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    def SetCalcMFPBattleAttr(self, allAttrList):
        battleAttrDict = allAttrList[ChConfig.CalcAttr_Battle]
        # ÉèÖñ¾Ä£¿éÔö¼ÓµÄÏßÐÔÕ½¶·ÊôÐÔ£¬·ÇÏßÐÔÕ½¶·ÊôÐÔÔö¼ÓµÄÔÚË¢ÊôÐÔʱÀÛ¼ÓÉÏÈ¥
        for attrIndex, value in battleAttrDict.items():
            self.AddCalcMFPAttr(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):
        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) # ±©»÷ÂÊ
        SuperHit = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHit) # ±©»÷É˺¦±¶ÂÊ
        SuperHitReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SuperHitReducePer) * fpParam.GetCftSuperHitReduce() # ±©»÷É˺¦¼õÃâ
        LuckyHitRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHitRate) # »áÐÄÒ»»÷
        LuckyHit = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHit) # »áÐÄÒ»»÷É˺¦±¶ÂÊ
        LuckyHitRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_LuckyHitRateReduce) * fpParam.GetCftLuckyHitRateReduce() # »áÐÄÒ»»÷¸ÅÂÊ¿¹ÐÔ
        SkillAtkRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SkillAtkRate) * fpParam.GetCftSkillAtkRate() # ¼¼Äܹ¥»÷±ÈÀý¼Ó³É
        SkillAtkRateReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_SkillAtkRateReduce) * fpParam.GetCftSkillAtkRateReduce() # ¼¼Äܹ¥»÷±ÈÀý¼õÉÙ
        DamagePer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePer) * fpParam.GetCftDamagePer() # É˺¦Êä³ö¼ÆËã°Ù·Ö±È
        DamReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AttrDamReduce) * fpParam.GetCftDamReduce() # É˺¦Êä³ö¼ÆËã°Ù·Ö±È¼õÉÙ, É˺¦ÎüÊÕ
        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) # ÒÆ¶¯ËÙ¶ÈÖµ
        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 = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_BleedDamage) * fpParam.GetCftBleedDamage() # Á÷ѪÉ˺¦
        AtkBackHP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_AtkBackHPPer) # ¹¥»÷»Ø¸´ÑªÁ¿
        FaintRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FaintRate) * fpParam.GetCftFaintRate() # ´¥·¢»÷ÔÎ
        FaintDefRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FaintDefRate) * fpParam.GetCftFaintDefRate() # »÷Ôεֿ¹
        FinalHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurt) # ×îÖչ̶¨É˺¦Ôö¼Ó
        FinalHurtReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_FinalHurtReduce) # ×îÖչ̶¨É˺¦¼õÉÙ
        DamagePerPVP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePerPVP) * fpParam.GetCftDamagePerPVP() # É˺¦Êä³ö¼ÆËã°Ù·Ö±ÈPVP
        DamagePerPVPReduce = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_DamagePerPVPReduce) * fpParam.GetCftDamagePerPVPReduce() # É˺¦Êä³ö¼ÆËã°Ù·Ö±ÈPVP¼õÉÙ
        ComboRate = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ComboRate) # Á¬»÷¼¸ÂÊ
        ComboDamPer = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ComboDamPer) # Á¬»÷É˺¦
        MaxProDef = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_MaxProDef) # ×î´ó·À»¤Öµ
        ProDefAbsorb = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_ProDefAbsorb) # ·À»¤ÖµÎüÊÕÉ˺¦±ÈÂÊ
        
        OnlyFinalHurt = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_OnlyFinalHurt) # ¶îÍâÊä³öÉ˺¦
        PVPAtkBackHP = getattr(self, self.__AttrName % ChConfig.TYPE_Calc_PVPAtkBackHP) # PVP¹¥»÷»ØÑª
        
        #ÆäËûÐè×÷Ϊ¹«Ê½²ÎÊýµÄϵÊý
        AtkSpeedParameter = fpParam.GetCftAtkSpeed()
        LuckyHitParameter = fpParam.GetCftLuckyHit()
        
        #»ñÈ¡²ß»®ÅäÖõıí¸ñ
        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)
        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
        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
    
    #---------------------------------------------------------------------
    ## »ñÈ¡ÏÂÒ»´ÎתÉúËùÐèµÈ¼¶
    def GetNextReincarnationLV(self, curPlayer):
        Reincarnation_ConditionDict = ReadChConfig.GetEvalChConfig("Reincarnation_Condition")
        curReinCnt = curPlayer.GetReincarnationLv() # µ±Ç°×ªÉú´ÎÊý
        nextReinCnt = curReinCnt + 1
        nextReinLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV")
        if nextReinCnt in Reincarnation_ConditionDict:
            nextReinLV = Reincarnation_ConditionDict[nextReinCnt][0]
        return nextReinLV
    
    ## ¼Ó¾ÑéÖµ 
    #  @param self ÀàʵÀý
    #  @param addExp Ìí¼ÓµÄ¾Ñé
    #  @param exp_rate ¾Ñé±¶ÂÊ
    #  @param expViewType ¾Ñé»ñµÃµÄÇþµÀ
    #  @param isSysHint ÊÇ·ñϵͳÌáʾ£¨Ä¬ÈÏÊÇ£©
    #  @return ²¼¶ûÖµ
    def AddExp(self, addExp, expViewType=ShareDefine.Def_ViewExpType_Mission, isSysHint=True):
        curPlayer = self.__Player
        finalAddExp, expNotifyType = self.__AddExp(curPlayer, addExp, expViewType, isSysHint)
        
        # ֪ͨ¿Í»§¶Ë¾ÑéÀ´Ô´
        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)
        
        # ¿ç·þÖлñµÃ¾Ñé
        if finalAddExp and GameWorld.IsMergeServer():
            PlayerMergeEvent.AddMSPlayerEvent(curPlayer.GetPlayerID(), PlayerMergeEvent.Def_MSPEvent_AddExp, finalAddExp)
            
        return finalAddExp
    
    def __AddExp(self, curPlayer, addExp, expViewType, isSysHint):
        if addExp == 0:
            # ²»½øÈë¼ÆËã
            return addExp, expViewType
        #nextReinLV = self.GetNextReincarnationLV(curPlayer)
        
        #È¡µÃÈËÎﵱǰ¾Ñé
        #curTotalExp = GetPlayerTotalExp(curPlayer)
        curTotalExp = curPlayer.GetExpPoint() * ChConfig.Def_PerPointValue + curPlayer.GetTotalExp()
        maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
        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)
            exp_rate += superRate
            if superRate:
                expViewType = ShareDefine.Def_ViewExpType_KillNPCSuper
                
        elif expViewType in [ShareDefine.Def_ViewExpType_GameEvent, ShareDefine.Def_ViewExpType_Sit]:
            exp_rate = curPlayer.GetGameEventExpRate()
        else:
            exp_rate = max(GameWorld.GetGameWorld().GetExpRate(), ChConfig.Def_MaxRateValue)
            
        #ÊäÈëµÄ¾ÑéÓпÉÄÜΪ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 = PlayerCostVIP.GetBZZDExpAddRate(curPlayer)
        #    #    #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 curPlayer.GetHP() <= 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
        
        playerNeedDoLVUp = False
        curLV = curPlayer.GetLV()
        maxLV = IpyGameDataPY.GetFuncCfg("PlayerMaxLV", 1)
        
        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)
            
            self.__DoLVUPAddPoint()  # Éý¼¶¼Óµã
            #self.__DoLvUpAddSkill()  # Éý¼¶¼Ó¼¼ÄÜ
            
            lvIpyData = GetPlayerLVIpyData(curPlayer.GetLV())
            # ´óʦÌ츳µã
            if lvIpyData:
                PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, lvIpyData.GetTalentPoint())
            
            EventShell.EventResponse_LVUp(curPlayer)  # Éý¼¶´¥·¢Ê¼þ
            
            #---ÊÇ·ñ¼ÌÐøÑ»·---
            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
                PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_HeroLV, aftLV)
            if aftFreePoint > befFreePoint:
                curPlayer.SetFreePoint(aftFreePoint)
                #NotifyCode(curPlayer, "ObtainAttributeDot", [aftFreePoint - befFreePoint])
            if aftBaseSTR > befBaseSTR:
                curPlayer.SetBaseSTR(aftBaseSTR)
            if aftBasePNE > befBasePNE:
                curPlayer.SetBasePNE(aftBasePNE)
            if aftBasePHY > befBasePHY:
                curPlayer.SetBasePHY(aftBasePHY)
            if aftBaseCON > befBaseCON:
                curPlayer.SetBaseCON(aftBaseCON)
            #===================================================================
            # if curPlayer.GetXP() != befXP:
            #    curPlayer.SetXP(curPlayer.GetXP())
            #===================================================================
                
            #ÏíÊÜÊÀ½çµÈ¼¶
            #===================================================================
            #curExpRate = PlayerWorldAverageLv.GetWorldAverageLvExpRate(curPlayer)
            #if beforeExpRate <= 0 and curExpRate > 0:
            #    NotifyCode(curPlayer, "GeRen_liubo_127574")
            
            #===================================================================
            
            # Éý¼¶ÐèÒªÖ´ÐеÄÓÎÏ·¹¦ÄÜ´¦Àí
            GameFuncComm.DoFuncOpenLogic(curPlayer)
            ChEquip.CalcEquips_OutOfPrint(curPlayer)    # »º´æ¾ø°æÊôÐÔ
            self.RefreshPlayerAttrState(billboardFunc=PlayerBillboard.UpdatePlayerLVBillboard)
            #·ÅÔÚ¹¦ÄÜ¿ªÆôºóÃæ
            PlayerWorldAverageLv.UpdatePlayerWorldAverageLv(curPlayer)
            #½«ÑªÉèÖÃΪ×î´ó
            curPlayer.SetHP(curPlayer.GetMaxHP())
            if curPlayer.GetMaxMP() > 0:
                curPlayer.SetMP(curPlayer.GetMaxMP())
                
            # ¼Ç¼¿ª·þ»î¶¯³å¼¶Êý¾Ý
            OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_LV, curPlayer.GetLV())
            
        #²»ÐèÒª×öÉý¼¶ÈÎÎñ, ÉèÖÃÍæ¼Ò¾Ñé
        SetPlayerTotalExp(curPlayer, curTotalExp) 
        return
    
    #---------------------------------------------------------------------
    def CalcRoleBaseAttr(self, curPlayer):
        # ¼ÆËãÍæ¼Ò½ÇÉ«»ù´¡ÊôÐÔÖµ
        
        curPlayerID = curPlayer.GetID()
        job = curPlayer.GetJob()
        
        lvAttrDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAttr%s" % job, 1)
        pointAttrDict = IpyGameDataPY.GetFuncEvalCfg("PointAttr%s" % job, 1)
        
        if not lvAttrDict:
            GameWorld.ErrLog('ÎÞ´ËÖ°ÒµµÈ¼¶Ë¢ÊôÐÔÅäÖÃ!job=%s' % (job), curPlayerID)
            return
        if not pointAttrDict:
            GameWorld.ErrLog('ÎÞ´ËÖ°ÒµÊôÐÔµãË¢ÊôÐÔÅäÖÃ!job=%s' % (job), curPlayerID)
            return
        
        #²ÎÓë¼ÆËãµÄÍæ¼Ò»ù´¡ÊôÐÔ
        LV = curPlayer.GetLV()
        STR = curPlayer.GetSTR()
        PNE = curPlayer.GetPNE()
        PHY = curPlayer.GetPHY()
        CON = curPlayer.GetCON()
        baseSTR = curPlayer.GetBaseSTR()
        basePNE = curPlayer.GetBasePNE()
        basePHY = curPlayer.GetBasePHY()
        baseCON = curPlayer.GetBaseCON()
        GameWorld.DebugLog("CalcRoleBaseAttr LV=%s,STR=(%s~%s),PNE=(%s~%s),PHY=(%s~%s),CON=(%s~%s)" 
                           % (LV, baseSTR, STR, basePNE, PNE, basePHY, PHY, baseCON, CON))
        
        allAttrList = [{} for _ in range(4)]
        
        # Ö°Òµ³õʼÊôÐÔ
        roleBaseAttrDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 1)
        if job in roleBaseAttrDict:
            for attrEffID, value in roleBaseAttrDict[job].items():
                CalcAttrDict_Type(attrEffID, value, allAttrList)
        #GameWorld.DebugLog("³õʼ¼ÓÊôÐÔ: %s" % allAttrList)
        for attrEffID, formula in lvAttrDict.items():
            calcValue = eval(FormulaControl.GetCompileFormula("LVUPAttr%s_%s" % (job, attrEffID), formula))
            CalcAttrDict_Type(attrEffID, calcValue, allAttrList)
            #GameWorld.DebugLog("    attrEffID=%s,value=%s" % (attrEffID, calcValue))
        #GameWorld.DebugLog("µÈ¼¶¼ÓÊôÐÔ: %s" % allAttrList)
        
        for attrEffID, formula in pointAttrDict.items():
            calcValue = eval(FormulaControl.GetCompileFormula("PointAttr%s_%s" % (job, attrEffID), formula))
            CalcAttrDict_Type(attrEffID, calcValue, allAttrList)
            #GameWorld.DebugLog("    attrEffID=%s,value=%s" % (attrEffID, calcValue))
        #GameWorld.DebugLog("µÈ¼¶ÊôÐÔµã¼ÓÊôÐÔ: %s" % allAttrList)
        
        SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_RoleBase, allAttrList)   
        return
    
    #---------------------------------------------------------------------
    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
            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)
        #SkillShell.RefreshPlayerBuffOnAttrAddEffect(curPlayer)
        PlayerWing.CalcWingAttr(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)
        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 = curPlayer.GetMaxHP()
        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):
        ''' ±¾ÏîĿˢÊôÐÔ¹æÔò
                ¹¦ÄÜÊôÐԲ㼶һ(ÏßÐԲ㼶¡¢·ÇÏßÐԲ㼶)
                ¹¦ÄÜÊôÐԲ㼶¶þ(ÏßÐԲ㼶¡¢·ÇÏßÐԲ㼶)
                ...
                ¹Ì¶¨ÊôÐԲ㼶
              buff²ã¼¶
              
            1. ³õʼ»¯
            
            ¹¦ÄÜÊôÐԲ㼶һ¡¢
            2.»ù´¡ÊôÐÔ¼ÆËã
            3.Õ½¶·ÊôÐÔ¼ÆËã
                ÏßÐԲ㼶ÊôÐÔ:  »ù´¡²ã¼¶ÊôÐÔ + ¹¦Äܲ㼶ÊôÐÔ
                    »ù´¡²ã¼¶ÊôÐÔ£º½ÇÉ«»ù´¡ÊôÐÔ£¨µÈ¼¶ÌáÉý + ÊôÐÔµãÌáÉý£© + ×°±¸ÎïÆ·±í»ù´¡ÊôÐÔ + ²¿Î»Ç¿»¯»ù´¡ÊôÐÔ
                    ¹¦Äܲ㼶ÊôÐÔ£ºÉñ±ø + ×øÆï + È«Éí²¿Î»Ç¿»¯ÐǼ¶ÀÛ¼Ó + Õ䯷 + ʱװ + Ì××° + ±¦Ê¯ + Õ½Ã˿Ƽ¼ + ·ûÎÄ + ÊØ»¤ µÈ
                    
                                    ×¢Ò⣺¸Ã²ãÖл¹°üº¬Õë¶Ô»ù´¡ÊôÐÔ»ò¹¦ÄÜÊôÐÔµÄÊýÖµ°Ù·Ö±ÈÌáÉý£¬´ËÌáÉýÖµÒ²ÊÇÀÛ¼Óµ½ÏßÐԲ㼶ÊôÐÔ
                                    Èç: ¡¾»ù´¡¹¥»÷°Ù·Ö±È¡¿¼´¶Ô »ù´¡ÊôÐÔ Öй¥»÷ÊôÐÔ°Ù·Ö±ÈÌáÉý
                                    ¡¾Éñ±øÉúÃüÊôÐ԰ٷֱȡ¿¼´¶Ô Éñ±ø¹¦ÄÜÊôÐÔ ÖÐÉúÃüÊôÐÔ°Ù·Ö±ÈÌáÉý
                                    ÀàËÆ´ËÀàÊôÐÔ²¢²»ÊÇÕæÕýÒâÒåÉϵķÇÏßÐÔÊôÐÔ£¬½öÊǶÔij¸ö¹¦ÄÜ»ò¹¦ÄÜ×éµÄ¶ÔÓ¦ÊôÐÔ½øÐаٷֱÈÌáÉý£¬×îÖÕµÄÌáÉýÖµ»¹ÊÇËãÈçÏßÐÔÊôÐÔ²ã
                    
                ·ÇÏßÐԲ㼶ÊôÐÔ: ¼´ÕûÌå²ã¼¶°Ù·Ö±ÈÔö¼ÓÊôÐÔ
                    Ö±½ÓÒÔµ±Ç°ÊôÐÔΪ»ùÖµ½øÐÐÊôÐÔ°Ù·Ö±ÈÌáÉý
            ¹¦ÄÜÊôÐԲ㼶¶þ¡¢
            ...
              
            4.¹Ì¶¨ÊôÐÔ:
                    ¸½¼ÓµÄ¹Ì¶¨ÖµÊôÐÔ£¬¸ÃÊôÐÔÔÚ·ÇÏßÐÔ¼ÆËãÖ®ºó£¬Ö±½ÓÀÛ¼Ó£¬²»ËãÈë·ÇÏßÐÔÊôÐԵĻùÖµ
            
            5.¼ÆËãÒÔÉÏËùÓÐÊôÐÔµÄÕ½¶·Á¦
            
            6.buff²ã¼¶£º
                    ¹Ì¶¨Öµbuff£¬ Ö±½ÓÀÛ¼ÓÊýÖµ
                    °Ù·Ö±Èbuff£º ÕæÕýµÄ×î×î×îÍâ²ã£¬Ö±½Ó°´°Ù·Ö±ÈÌáÉý¶ÔÓ¦µÄÊôÐÔÖµ
                    ×¢£º¸Ã²ãÌáÉýµÄÊôÐÔ²»ËãÕ½¶·Á¦
        '''
        curPlayer = self.__Player
        
        if curPlayer.GetDictByKey(ChConfig.Def_Player_RefreshAttr) != 1:
            return False
        
        GameWorld.DebugLog("Start RefreshPlayerAttrStateEx!!!")
        
        #beforeAtkInterval = curPlayer.GetAtkInterval()
        beforeMaxHP = curPlayer.GetMaxHP()
        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.ResetFightPowerObj()
        #self.PrintAttr(curPlayer, "ÖØÖúó")
        
        # 1.³õʼ»¯ÈËÎï¸÷Ïî״̬¼°ÊôÐÔ
        self.InitPlayerState()        
        #self.PrintAttr(curPlayer, "³õʼ»¯")
        
        # ¹¦ÄÜÊôÐԲ㼶һ...
        # 2.¼ÆËã»ù´¡ÊôÐÔ
        #    2.1 »ñÈ¡ËùÓй¦ÄܼÆËãµã¼ÆËãµÄÊôÐÔÖµ, ͳ¼Æ»ù´¡ÊôÐÔÀÛ¼Ó
        baseAttrDict = {}
        baseAttrNolineDict = {}
        roleBaseAttrInfo = [{} for _ in range(4)]
        funcAttrInfoList = []
        for funcIndex in ChConfig.CalcAttrFuncList:
            if funcIndex in ChConfig.CalcAttrExFuncListNoFightPower:
                # ´ËÀ๦Äܲ»ËãÕ½¶·Á¦
                funcAttrInfoList.append([{} for _ in range(4)]) # ֻΪ·ÀÖ¹ºóÃæ·ÃÎÊÁбíÔªËØÊ±²»Ô½½ç, ¹¦Äܵã·ÖÀà¿ÉÎÞÊÓ±àºÅ˳Ðò
                continue
            
            # »ù´¡ÊôÐԵȹ¦ÄÜ»ã×ÜÍêºóͳһˢУ¬ÒòΪ¸÷¹¦ÄÜ¿ÉÄÜ»á¼ÓÊôÐÔµãÊý
            if funcIndex == ChConfig.Def_CalcAttrFunc_RoleBase:
                funcAttrInfoList.append(roleBaseAttrInfo)
                continue
            attrInfo = GetCalcAttrListValue(curPlayer, funcIndex)
            GameWorld.DebugLog("¹¦ÄܵãÊôÐÔ: %s, %s" % (funcIndex, attrInfo))
            funcAttrInfoList.append(attrInfo)
            # ²»Í¬¹¦Äܵã¼äµÄÊýÖµÀÛ¼Ó£¬ÐèʹÓÃÖ§³ÖË¥¼õµÝÔöµÄ¼ÆË㷽ʽ
            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)
            
        # ¹¦ÄÜÓмӻù´¡ÊôÐÔÖµ£¬ÕâÀïÔÙÖØÐÂË¢ÐÂһϻù´¡ÊôÐÔ, »ù´¡ÊôÐÔ»áÓ°ÏìÕ½¶·ÊôÐÔ, ÿ´Î¶¼Ë¢Ð½ÇÉ«»ù´¡ÊôÐÔ
        self.CalcRoleBaseAttr(curPlayer)
        roleBaseAttrInfo = GetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_RoleBase)
        funcAttrInfoList[ChConfig.Def_CalcAttrFunc_RoleBase] = roleBaseAttrInfo
        GameWorld.DebugLog("¹¦ÄܵãÊôÐÔ: %s, %s" % (ChConfig.Def_CalcAttrFunc_RoleBase, roleBaseAttrInfo))
        
        #self.PrintAttr(curPlayer, "»ù´¡ºó")
        
        # 3.¼ÆËãÕ½¶·ÊôÐÔ
        #    3.1 Õ½¶·ÊôÐԲ㼶½»²æÓ°Ïì»ùÖµÊýÖµ»ã×Ü
        #        ×°±¸»ù´¡
        equipBaseAttrList = AddAttrListValue([funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseWeapon],
                                              funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseArmor],
                                              funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseRelics],
                                              ])
        #GameWorld.DebugLog("×°±¸»ù´¡: %s" % equipBaseAttrList)
        
        #        »ù´¡²ã¼¶(½ÇÉ«»ù´¡ÊôÐÔ¡¢×°±¸»ù´¡ÊôÐÔ¡¢Ç¿»¯»ù´¡ÊôÐÔ)
        baseAttrList = AddAttrListValue([funcAttrInfoList[ChConfig.Def_CalcAttrFunc_RoleBase],
                                         equipBaseAttrList,
                                         funcAttrInfoList[ChConfig.Def_CalcAttrFunc_PlusBase],
                                         ])
        #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_EquipBaseAddPer:equipBaseAttrList,
                           ChConfig.TYPE_Calc_WeaponAtkAddPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseWeapon],
                           ChConfig.TYPE_Calc_RelicsAtkAddPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseRelics],
                           ChConfig.TYPE_Calc_ArmorMaxHPAddPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseArmor],
                           ChConfig.TYPE_Calc_ArmorDefAddPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_EquipBaseArmor],
                           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_HorcruxBasePer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Horcrux],
                           ChConfig.TYPE_Calc_WingHPPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Wing],
                           ChConfig.TYPE_Calc_SuiteBasePer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_Suit],
                           ChConfig.TYPE_Calc_PlusBaseAtkPer:funcAttrInfoList[ChConfig.Def_CalcAttrFunc_PlusBase],
                           }
        #    3.2 ͳ¼Æ¸÷¹¦ÄÜÖ®¼ä·ÇÏßÐÔÊôÐÔ½»²æÓ°ÏìÀÛ¼Ó
        funcAddAttrPerInfoDict = {} # °Ù·Ö±È½»²æÓ°ÏìËùÌáÉýµÄÊôÐÔÖµ {¹¦ÄÜÊôÐÔ±àºÅ:{ÌáÉýµÄÊôÐÔÀàÐÍ:ÊýÖµ, ...}, ...}
        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:
                # Ôö¼ÓµÄÊýֵͳ¼Æµ½°Ù·Ö±ÈÊôÐÔËùÊô¹¦Äܵã
                # Èç·ûÎÄÓиöÎäÆ÷¹¥»÷°Ù·Ö±ÈÔö¼ÓÊôÐÔ£¬Ôö¼ÓµÄÊýÖµÊôÓÚ·ûÎŦÄÜ£¬²»ÊôÓÚÎäÆ÷¹¦ÄܵãµÄ£¬Ö»ÊÇ»ùֵʹÓÃÁËÎäÆ÷¹¥»÷     
                funcAddAttrPerInfoDict[i] = addAttrDict # Ïȶ¼Í³¼ÆÍêºóÔÙÀÛ¼Óµ½¶ÔÓ¦¹¦ÄÜÊôÐÔÀ²»È»¿ÉÄܻᵼÖ¹¦ÄÜ»ùÖµ±ä¸ü
                
        GameWorld.DebugLog("½»²æÓ°ÏìÊôÐÔ: %s" % funcAddAttrPerInfoDict)
        #        ½»²æÌáÉýµÄÊôÐÔÖµÀÛ¼Óµ½¶ÔÓ¦¹¦ÄÜÉÏ
        for i, addAttrDict in funcAddAttrPerInfoDict.items():
            # ÕâÀïÀÛ¼ÓµÄÊǵ½ÏàͬµÄ¹¦Äܵ㣬ֱ½ÓÀÛ¼Ó£¬²»×öË¥¼õ´¦Àí
            GameWorld.AddDictValue(funcAttrInfoList[i][ChConfig.CalcAttr_Battle], addAttrDict)
            
        #    3.3 ÀÛ¼ÓÒÔÉÏÒÑͳ¼ÆµÄËùÓÐÊôÐÔ£¨ÊÓΪÕûÌå²ã¼¶£¬¼´·ÇÏßÐÔÊôÐÔËùÐèÒªµÄ»ùÖµ£©
        allFuncAttrIndexList = []
        allFuncAttrInfoList, attrInfoExList = [], [] # ÕûÀí¹¦Äܲ㼶ÊôÐÔÐÅÏ¢Áбí, ¶îÍ⸽¼Ó¹Ì¶¨ÖµÊôÐÔÐÅÏ¢Áбí
        for funcIndex, attrInfo in enumerate(funcAttrInfoList):
            if funcIndex not in ChConfig.CalcAttrExFuncList:
                allFuncAttrIndexList.append(funcIndex)
                allFuncAttrInfoList.append(attrInfo)
            else:
                attrInfoExList.append(attrInfo)
        allAttrList = AddAttrListValue(allFuncAttrInfoList) # ²»Í¬¹¦Äܵã¼äµÄÊýÖµÀÛ¼Ó£¬ÐèʹÓÃÖ§³ÖË¥¼õµÝÔöµÄ¼ÆË㷽ʽ
        GameWorld.DebugLog("ÕûÌå²ã¼¶¹¦Äܵã: %s" % allFuncAttrIndexList)
        GameWorld.DebugLog("ÕûÌå²ã¼¶ÏßÐÔÊôÐÔ: %s" % allAttrList)
        
        #        µÚ¶þ²ã¼¶ÊôÐÔ
        allAttrExList = AddAttrListValue(attrInfoExList)
        GameWorld.DebugLog("¸½¼Ó²ã¼¶¹¦Äܵã: %s" % ChConfig.CalcAttrExFuncList)
        GameWorld.DebugLog("¸½¼Ó²ã¼¶ÏßÐÔÊôÐÔ: %s" % allAttrExList)
        
        #        ³õʼ»¯¸÷¹¦ÄܵãÕ½¶·Á¦¼ÆËãÄ£¿é
        mfpObjAttrDict = {}
        for mfpType, attrFuncIndexList in ChConfig.MFPTypeAttrFuncIndexDict.items():
            if len(attrFuncIndexList) == 1:
                mfpAttrList = funcAttrInfoList[attrFuncIndexList[0]]
            else:
                mfpAttrList = AddAttrListValue([funcAttrInfoList[i] for i in attrFuncIndexList])
            
            #GameWorld.DebugLog("Ä£¿éÏßÐÔÊôÐÔ: mfpType=%s,%s" % (mfpType, mfpAttrList))
            mfpObj = self.GetModuleFightPowerObj(mfpType)
            mfpObj.SetCalcMFPBattleAttr(mfpAttrList)
            mfpObjAttrDict[mfpObj] = mfpAttrList[ChConfig.CalcAttr_BattleNoline]
            
        #         ²»¼ÓÕ½Á¦£¬µ«ÊÇÓÐËãÊôÐԵŦÄÜÊôÐÔ£¬ÈçһЩ±»¶¯¼¼ÄÜ£¨Õ½Á¦ÔÚ¼¼ÄܱíÀïÅäÖã©
        skillNoFightPowerAttrList = [{} for _ in range(4)]
        SkillShell.CalcPassiveAttr_Effect(curPlayer, skillNoFightPowerAttrList)  # ÊôÐÔÀ༼ÄÜÓëbuffͬ²ã
        for funcIndex in ChConfig.CalcAttrExFuncListNoFightPower:
            skillNoFightPowerAttrList = AddAttrListValue([skillNoFightPowerAttrList, GetCalcAttrListValue(curPlayer, funcIndex)])    
        GameWorld.DebugLog("ÎÞÕ½Á¦±»¶¯ÊôÐÔ: %s" % skillNoFightPowerAttrList)
        
        # ×ÜÊôÐÔ = ÕûÌ幦Äܲ㼶¹Ì¶¨Öµ*(1+¹¦Äܲ㼶°Ù·Ö±È+ÌØÊâ¹Ì¶¨²ã¼¶°Ù·Ö±È+ÓÀ¾Ã¼¼Äܲ㼶°Ù·Ö±È)+ÌØÊâ¹Ì¶¨²ã¼¶¹Ì¶¨Öµ+ÓÀ¾Ã¼¼Äܲ㼶¹Ì¶¨Öµ
        allNoLineAttrDict = {}
        AddAttrDictValue(allNoLineAttrDict, allAttrList[ChConfig.CalcAttr_BattleNoline])
        AddAttrDictValue(allNoLineAttrDict, allAttrExList[ChConfig.CalcAttr_BattleNoline])
        AddAttrDictValue(allNoLineAttrDict, skillNoFightPowerAttrList[ChConfig.CalcAttr_BattleNoline])
        GameWorld.DebugLog("×îÖÕ·ÇÏßÐÔÊôÐÔ: %s" % allNoLineAttrDict)
        
        #        ÕûÌå²ã¼¶ÊôÐÔÔö¼Óµ½Íæ¼ÒÉíÉÏ
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, allAttrList[ChConfig.CalcAttr_Battle])
        #self.PrintAttr(curPlayer, "ÕûÌåÏß")
        CalcNoLineEffect.ChangePlayerAttrInNoLineEffectList(curPlayer, allNoLineAttrDict, mfpObjAttrDict)
        #self.PrintAttr(curPlayer, "Õû·ÇÏß")
        
        
        # 4.¼ÆËãÕ½Á¦, ÐèÔÚ¼ÆËãbuff²ã֮ǰ¼ÆËã
        curLV = curPlayer.GetLV()
        fpParam = IpyGameDataPY.GetIpyGameData("FightPowerParam", curLV)
        mfpDict = {} # Ä£¿éÕ½¶·Á¦
        for mfpObj in mfpObjAttrDict.keys():
            mfpDict[mfpObj.mfpType] = 0 if not fpParam else mfpObj.GetModuleFightPower(fpParam)
            mfpDict[mfpObj.mfpType] = mfpDict[mfpObj.mfpType] + curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPSkill % mfpObj.mfpType)
            mfpDict[mfpObj.mfpType] = mfpDict[mfpObj.mfpType] + curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPEx % mfpObj.mfpType)
            
        #        ×îºóÔÚ¸½¼ÓÉÏÌØÊ⸽¼Ó²ã¼¶ÏßÐÔÊôÐÔ¡¢ÓÀ¾Ã¼¼Äܲ㼶¹Ì¶¨Öµ
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, allAttrExList[ChConfig.CalcAttr_Battle])
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, skillNoFightPowerAttrList[ChConfig.CalcAttr_Battle])
        #self.PrintAttr(curPlayer, "¹Ì¶¨²ã¼¶")
        
        # ¡¾µ½´ËËùÓй¦ÄÜÊôÐÔ¶¼ÒÑˢд¦ÀíÍê±Ï£¬¸´ÖÆÒ»·Ý ¹¦ÄÜÊôÐÔµÄˢнá¹û£¬ÓÃÓÚBUFFÊôÐÔµ¥¶ÀˢС¿
        EffGetSet.CopyPlayerFuncAttr(curPlayer)
        
        # 6.¼ÆËãbuffÊôÐÔ, buff²ã¼¶µÄ²»ËãÈçÕ½¶·Á¦
        self.__RefreshBuffAttr()
        
        # 7.Ë¢ÍêÊôÐÔºóÐèÒª´¦ÀíµÄÂß¼
        self.__DoRefreshAttrAfterLogic(beforeMaxHP, beforeMoveSpeedValue, playerStateDict)
        
        #֪ͨ»ù´¡ÊôÐÔ
        self.__SyncBaseAttr(curPlayer, baseAttrList)
        
        # ͬ²½Ç°¶ËÕ½Á¦£¬ÒòΪÓÐ 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)
        GameWorld.DebugLog("End RefreshPlayerAttrStateEx!!!")
        return True
    
    
    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.ChangePlayerAttrInNoLineEffectList(curPlayer, battleNolineAttrBuff, isBuffAttr=True)
        
        battleAttrBuff = allAttrListBuffs[ChConfig.CalcAttr_Battle]
        CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, battleAttrBuff, isBuffAttr=True)
        
        #        ËÙ¶ÈÌØÊâ´¦Àí ¼ÆËãÒ»´Î
        self.__RefreshMoveSpeed(allAttrListBuffs)
        
        #        ˢй¥»÷ËÙ¶È
        self.__SetAtkInterval()
        GameWorld.DebugLog("Buff²ãÊôÐÔ: %s" % allAttrListBuffs)
        
        # GM²âÊÔÊôÐÔÌØÊâÂß¼
        self.__DoRefreshGMAttr()    
        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() * attrPer) # ¹¥»÷ËÙ¶È
                setAttrDict[ChConfig.AttrName_SkillAtkRate] = int(lvIpyData.GetReSkillAtkRate() * attrPer) # ¼¼ÄÜÉ˺¦±ÈÀý
                setAttrDict[ChConfig.AttrName_DamagePer] = int(lvIpyData.GetReDamagePer() * attrPer) # Ôö¼ÓÉ˺¦
                setAttrDict[ChConfig.AttrName_DamReducePer] = int(lvIpyData.GetReDamReduce() * attrPer) # ¼õÉÙÉ˺¦
                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(lvIpyData.GetRePetSkillAtkRate() * attrPer) # Áé³è¼¼ÄÜ
                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 = curPlayer.GetMaxHP()
        addMaxHP = max(0, afterMaxHP - beforeMaxHP)
        if beforeMaxHP > 0 and addMaxHP > 0 and curPlayer.GetPlayerAction() != IPY_GameWorld.paDie:
            # ×î´óѪÁ¿Ôö¼Óʱ£¬Í¬²½Ôö¼ÓµÈÁ¿µÄµ±Ç°ÑªÁ¿ (ËÀÍö״̬ϲ»Ë¢µ±Ç°ÑªÁ¿)
            curPlayer.SetHP(min(curPlayer.GetHP() + 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())
        
        #³èÎïÊý¾Ý¹ÒÔÚÎïÆ·ÉÏ£¬µ¥¶À¼ÆËã
        PlayerPet.SetPetSkillFightPower(curPlayer) 
        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
    
    ## ¼ÆËã±»¶¯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 # ÀÛ¼Ó×ÜÕ½¶·Á¦
            
        if totalFightPower > ShareDefine.Def_UpperLimit_DWord:
            GameWorld.ErrLog("×ÜÕ½Á¦³¬¹ýÊýÖµÉÏÏÞ£¡totalFightPower=%s" % totalFightPower, curPlayer.GetPlayerID())
            totalFightPower = ShareDefine.Def_UpperLimit_DWord
            
        # //A3 A1 ¸÷¹¦ÄÜÄ£¿éÕ½¶·Á¦ÐÅÏ¢ #tagMCModuleFightPowerInfo
        mfpInfo = ChPyNetSendPack.tagMCModuleFightPowerInfo()
        mfpInfo.Clear()
        
        mfpInfo.TotalFightPower = totalFightPower
        mfpInfo.MFPCnt = len(mfpDataList)
        mfpInfo.MFPList = mfpDataList
        NetPackCommon.SendFakePack(curPlayer, mfpInfo)
        
        curPlayer.SetFightPower(totalFightPower, False)
        highestFightPower = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FightPower_Highest, 0,
                                                           ChConfig.Def_PDictType_FightPower)
        if totalFightPower > highestFightPower:
            NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FightPower_Highest, totalFightPower,
                                 ChConfig.Def_PDictType_FightPower)
        GameWorld.DebugLog("×ÜÕ½Á¦: %s, ÀúÊ·×î¸ßÕ½Á¦: %s" % (totalFightPower, highestFightPower))
        PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
        # ¼Ç¼¿ª·þ»î¶¯Êý¾Ý
        OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_FightPower, totalFightPower)
        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))
                
        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 = 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 __SetPlayerStateInDB(self):
        curPlayer = self.__Player
        #Á¦Á¿
        curPlayerSTR = curPlayer.GetSTR()
        if curPlayer.GetTotalSTR() != curPlayerSTR: 
            curPlayer.SetTotalSTR(curPlayerSTR)
        #ÕæÔª
        curPlayerPNE = curPlayer.GetPNE()
        if curPlayer.GetTotalPNE() != curPlayerPNE:
            curPlayer.SetTotalPNE(curPlayerPNE)
        #½î¹Ç
        curPlayerPHY = curPlayer.GetPHY()
        if curPlayer.GetTotalPHY() != curPlayerPHY:
            curPlayer.SetTotalPHY(curPlayerPHY)
        #ÌåÆÇ
        curPlayerCON = curPlayer.GetCON()
        if curPlayer.GetTotalCON() != curPlayerCON: 
            curPlayer.SetTotalCON(curPlayerCON)
        
        return
    
    #---------------------------------------------------------------------
    ## Ë¢ÐÂѪÁ¿ºÍħ
    #  @param self ÀàʵÀý
    #  @return ·µ»ØÖµÎÞÒâÒå
    #  @remarks Ë¢ÐÂѪÁ¿ºÍħ
    def __RestoreHPMP(self):
        curPlayer = self.__Player
        
        if not curPlayer.GetInitOK():
            #Íæ¼Òδ³õʼ»¯³É¹¦, ²»ÐÞÕýѪÁ¿ºÍħ·¨Öµ, Òò´ËʱÓпÉÄÜÒòΪijЩӰÏìÖ÷½ÇµÄÎïÆ·Î´³õʼ»¯Íê±Ï(Èç³èÎï×°±¸)
            return
        
        curPlayerHP = curPlayer.GetHP()
        curPlayerMaxHP = curPlayer.GetMaxHP()
        #=======================================================================
        # curPlayerMP = curPlayer.GetMP()
        # curPlayerMaxMP = curPlayer.GetMaxMP()
        #=======================================================================
        
        if curPlayerHP > curPlayerMaxHP:
            curPlayer.SetHP(curPlayerMaxHP)
        
        #=======================================================================
        # 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_SuperHit:ChConfig.Def_SuperHitPercent,
                        #ChConfig.TYPE_Calc_GreatHit:ChConfig.Def_GreatHitVal,
                        #ChConfig.TYPE_Calc_LuckyHit:ChConfig.Def_LuckyHitVal,
                        }
        
        for i in xrange(1, ChConfig.Def_Calc_AllAttrType_MAX):
            if i in [ChConfig.TYPE_Calc_AttrHP, ChConfig.TYPE_Calc_AttrMP]:
                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)
            
        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 curPlayer.GetHP() != 0:
            curPlayer.SetHP(0)
        
        #Çå¿ÕÒÆ¶¯´íÎó¾àÀë
        GameWorld.ClearPlayerPosCount(curPlayer)
        
        #¼Ç¼Ö÷½ÇËÀÍö´ÎÊýºÍËÀÍöʱ¼ä
        self.SetPlayerDeadCnt(curPlayer)
        
        #ËÀÍö´¥·¢¼¼ÄÜ
        tick = GameWorld.GetGameWorld().GetTick()
        
        #֪ͨËÀÍö
        DoPlayerDead(curPlayer)
        
        PlayerTJG.PlayerTJGReborn(curPlayer, tick)
        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 = []
    
    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()])
        #ɾ³ýÕâ¸ö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()
#---------------------------------------------------------------------
##Çå³ýÉú²ú²É¼¯BUF
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @param isLeaveServer Íæ¼ÒÊÇ·ñÀ뿪·þÎñÆ÷
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Çå³ýÉú²ú²É¼¯BUF
def DelProduceBuff(curPlayer, tick, isLeaveServer=False):
    
    if not isLeaveServer:
        if curPlayer.GetPlayerAction() != IPY_GameWorld.paProduce:
            #Íæ¼Òµ±Ç°×´Ì¬²»ÔÚÉú²ú²É¼¯£¬²»´¦Àí
            return
    
    #Çå³ýÉú²úbuff(ID20021)
    BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_ProduceBuffID, tick)
    
    #Çå³ý»î¶¯ÎÞµÐBuff
    BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_ActionWuDi, tick)
    
    if not isLeaveServer:
        #ÉèÖÃÍæ¼Ò¿ÕÏÐ״̬
        ChangePlayerAction(curPlayer, IPY_GameWorld.paNull)
        #֪ͨ¿Í»§¶Ë
        curPlayer.Notify_ProductionState(ChConfig.Def_EndProduction)
        
        #PlayerControl(curPlayer).RefreshAllState()
    return
    
#---------------------------------------------------------------------
##ÌØÊâ״̬´¦Àí
# @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 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) \
        and curPlayer.GetLV() >= actExpRateInfo.get(ShareDefine.ActKey_LVLimit, 0):
        fightExpRate += actExpRateInfo.get(ShareDefine.ActKey_AddExpRate, 0)
    
    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 job Ö°ÒµÀàÐÍ
#  @return baseSTR, basePNE, basePHY, baseCON
def GetPlayerBasePoint(job):
    baseSTR, basePNE, basePHY, baseCON = (0, 0, 0, 0)
    
    jobDict = IpyGameDataPY.GetFuncEvalCfg("CreatRolePoint%s" % job, 1)
    
    if not jobDict:
        GameWorld.ErrLog('CreatRolePoint, job = %s' % (job))
        return baseSTR, basePNE, basePHY, baseCON
    
    for key, value in jobDict.items():
        
        if type(key) == str:
            key = key.upper()
        
        if key in ['STR', ShareDefine.Def_Effect_STR]:
            baseSTR = value
            
        elif key in ['PNE', ShareDefine.Def_Effect_PNE]:
            basePNE = value
        
        elif key in ['PHY', ShareDefine.Def_Effect_PHY]:
            basePHY = value
        
        elif key in ['CON', ShareDefine.Def_Effect_CON]:
            baseCON = value
        
        else:
            GameWorld.ErrLog('CreatRolePoint, key = %s' % (key))
            
    return baseSTR, basePNE, basePHY, baseCON
##¼ÇÂ¼Íæ¼Òʧȥ½ðÇ®µÄÁ÷Ïò¼Ç¼£¬ÏûÏ¢Öлá¼ÇÂ¼Íæ¼ÒÓµÓеĽðÇ®ÐÅÏ¢
# @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
#
# ·¢ËÍ0418°ü
# SendPropertyRefresh(int inputType, int inputValue, bool boardCast, bool includeSelf = true)
# @param : boardCast-ÊÇ·ñ¹ã²¥ÖÜÎ§Íæ¼Ò£»includeSelf-ÊÇ·ñ°üº¬×Ô¼º
#
# ֪ͨGsmeServer; 
# SendGameServerRefreshState(int inputType, int inputValue)
# ½ûÑÔ Í¨ÖªgameServer
def SetGMForbidenTalk(curPlayer, value):
    curPlayer.SetGMForbidenTalk(value)
    curPlayer.SendGameServerRefreshState(ShareDefine.CDBPlayerRefresh_ForbidenTalk, value)
    return
## Ö°Òµ½×Êý
def GetJobRank(curPlayer): return curPlayer.GetExAttr1()
def SetJobRank(curPlayer, jobRank): 
    curPlayer.SendGameServerRefreshState(IPY_GameWorld.CDBPlayerRefresh_ExAttr1, jobRank)
    return curPlayer.SetExAttr1(jobRank)
## ¶ÓÎéÏà¹ØÉóºË¿ª¹Ø×´Ì¬, 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, False)
def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3()
## ÍÇ®µã, Ö§³ÖÍÇ®³¬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 curPlayer.GetExAttr9()
def SetVIPExpireTime(curPlayer, expireTime): return curPlayer.SetExAttr9(expireTime, False, True)
##»ñµÃÍæ¼ÒÍþÍûÖµ
def GetPrestige(curPlayer): return 0
def SetPrestige(curPlayer, value): return
## ÉèÖÃÄ£¿éÕ½¶·Á¦
def SetMFPFightPower(curPlayer, mfpType, fightPower):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPFightPower % mfpType, fightPower)
    return
## »ñȡģ¿éÕ½¶·Á¦
def GetMFPFightPower(curPlayer, mfpType):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MFPFightPower % 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)
    if GameWorld.IsMergeServer():
        eventInfo = [addValue, eventName, eventData]
        PlayerMergeEvent.AddMSPlayerEvent(curPlayer.GetPlayerID(), PlayerMergeEvent.Def_MSPEvent_AddZhenQi, eventInfo)
    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ÕæÆøÖµ
def GetZhenQi(curPlayer): return 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 value ÊýÖµ
# @return None
def SetVsFightValue(curPlayer, value):
    return
##»ñÈ¡¾ö¶·Öµ(¾º¼¼³¡ÓÃ)
# @param curPlayer Íæ¼Ò
# @return ¾ö¶·Öµ
def GetVsFightValue(curPlayer):
    return 0
##»ñÈ¡¾º¼¼µã(¾º¼¼³¡ÓÃ)
# @param curPlayer Íæ¼Ò
# @return ¾º¼¼µã
def GetVsSportsPoint(curPlayer):
    return 0
##ÉèÖþº¼¼µã(²»¿ÉÖ±½Óµ÷ÓÃ)
# @param curPlayer Íæ¼Ò
# @return 
def __SetVsSportsPoint(curPlayer, value):
    return
##¾º¼¼µã¼õÉÙ(¾º¼¼³¡ÓÃ)
# @param curPlayer Íæ¼Ò
# @return 
def ReduceVsSportsPoint(curPlayer, value):
    curValue = GetVsSportsPoint(curPlayer)
    #µ÷ÓýӿÚ
    __SetVsSportsPoint(curPlayer, max(0, curValue - value))
    #lostValue ÄúʧȥÁË{%S1%}µã¾º¼¼µã
    NotifyCode(curPlayer, "Arena_pan_474794", [value])
    return    
    
##»ñµÃÁúÂöµÈ¼¶
# @param curPlayer Íæ¼Ò
# @return ÁúÂöµÈ¼¶
def GetLongMaiLV(curPlayer):
    return 0
##ÉèÖÃÁúÂöµÈ¼¶
# @param curPlayer Íæ¼Ò
# @param value ÊýÖµ
# @return None
def SetLongMaiLV(curPlayer, value):
    return
#---------------------------------------------------------------------------
## ÉèÖÃÍæ¼Ò¿ç·þÔ¤ÈüÅÅλ
#  @param curPlayer: Íæ¼ÒʵÀý
#  @param value: ÍþÍûÖµ
#  @return: 
def SetMergeWarRank(curPlayer, value):
    curPlayer.SetExAttr10(value, True, True)
    return
    
## »ñÈ¡Íæ¼Ò¿ç·þÔ¤ÈüÅÅλ
#  @param curPlayer: Íæ¼ÒʵÀý
#  @return: ÍþÍûÖµ
def GetMergeWarRank(curPlayer):
    return curPlayer.GetExAttr10()
## ÉèÖÃÍæ¼Ò¹Ù¾ôÐǼ¶
#  @param curPlayer: Íæ¼ÒʵÀý
#  @param value: ÐǼ¶
#  @return: 
def SetOfficeStar(curPlayer, value):
    curPlayer.SetExAttr11(value)
    return
    
## »ñÈ¡Íæ¼ÒÍæ¼Ò¹Ù¾ôÐǼ¶
#  @param curPlayer: Íæ¼ÒʵÀý
#  @return: ÐǼ¶
def GetOfficeStar(curPlayer):
    return curPlayer.GetExAttr11()
##»ñÈ¡¿ÉÃâ·Ñ¿ªÆôµÄ¸ñ×ÓÊý
# @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()
## »ñµÃÍæ¼Òʵ¼ÊµÈ¼¶
#  @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
#===============================================================================
# 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
#===============================================================================
#---Íæ¼ÒÀ©Õ¹½Ó¿Ú, Õ½¶·ÊôÐÔ£¬²»´æÊý¾Ý¿â£¬Ö»Í¨Öª±¾ÈË---
##Íæ¼ÒÒÆ¶¯ËÙ¶ÈÖµ, ²»º¬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)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_SpeedValue, value, True) # ÒÆ¶¯ËÙ¶ÈÖµÔݶ¨¹ã²¥ÖÜÎ§Íæ¼Ò
##»ñÈ¡Íæ¼Ò¹¥»÷ËÙ¶È£¬ÓÃÓÚ¼ÆËã¹¥»÷¼ä¸ô
# @param curPlayer Íæ¼ÒʵÀý
# @return Íæ¼Ò¹¥»÷ËÙ¶È
def GetAtkSpeed(curPlayer):
    return curPlayer.GetBattleValEx1()
##ÉèÖÃÍæ¼Ò¹¥»÷ËÙ¶È£¬ÓÃÓÚ¼ÆËã¹¥»÷¼ä¸ô
# @param curPlayer Íæ¼ÒʵÀý
# @return None
def SetAtkSpeed(curPlayer, value):
    curPlayer.SetBattleValEx1(value, True)
    
#---¹¥»÷»Ø¸´ÑªÁ¿±ÈÂÊ----
## »ñÈ¡Íæ¼Ò¹¥»÷»Ø¸´ÑªÁ¿±ÈÂÊ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return 
def GetAtkBackHPPer(curPlayer):
    return curPlayer.GetBattleValEx2()
## ÉèÖÃÍæ¼Ò¹¥»÷»Ø¸´ÑªÁ¿±ÈÂÊ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return None
def SetAtkBackHPPer(curPlayer, value):
    curPlayer.SetBattleValEx2(value)
## »ñÈ¡Íæ¼Ò¹¥»÷»Ø¸´À¶Á¿±ÈÂÊ
def GetAtkBackMPPer(curPlayer): return 0
def SetAtkBackMPPer(curPlayer, value): return
## Íæ¼Ò¼õ¼¼ÄÜCDÖµ
def GetReduceSkillCD(curPlayer): return curPlayer.GetBattleValEx3()
def SetReduceSkillCD(curPlayer, reduceSkillCD):
    curPlayer.SetBattleValEx3(reduceSkillCD)
    reducePerFormat = ReadChConfig.GetChConfig("SkillCDReducePer")
    reducePer = eval(reducePerFormat)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ReduceSkillCDPer, reducePer)
    return
def GetReduceSkillCDPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ReduceSkillCDPer)
## ³£¹æµØÍ¼¾Ñé±¶ÂʼӳÉ
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)
#---Ö°ÒµÉ˺¦¼Ó³É---
## Ä¿±êսʿÉ˺¦¼Ó³É
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 GetLuckyHitReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_LuckyHitReducePer)
def SetLuckyHitReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_LuckyHitReducePer, value)
## ׿Խһ»÷É˺¦¼õÃâ
def GetGreatHitReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GreatHitReducePer)
def SetGreatHitReducePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GreatHitReducePer, value)
## ÖÂÃüÒ»»÷É˺¦¼õÃâ
def GetSuperHitReducePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuperHitReducePer)
def SetSuperHitReducePer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SuperHitReducePer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_SuperHitReduce, value, False)
## ÎÞÊÓ·ÀÓùÉ˺¦¼õÃâ
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)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_LuckyHitRateReduce, value, False)
## ¿¹×¿Ô½Ò»»÷¸ÅÂÊ
def GetGreatHitRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_GreatHitRateReduce)
def SetGreatHitRateReduce(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_GreatHitRateReduce, value)
## ¿¹ÖÂÃüÒ»»÷¸ÅÂÊ
def GetSuperHitRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuperHitRateReduce)
def SetSuperHitRateReduce(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SuperHitRateReduce, value)
## ¿¹ÎÞÊÓ·ÀÓù¸ÅÂÊ
def GetIgnoreDefRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_IgnoreDefRateReduce)
def SetIgnoreDefRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_IgnoreDefRateReduce, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_IgnoreDefRateReduce, value, False)
    
#---ÌØÊâÉ˺¦¸ÅÂÊ---
## ¸»¼×Ò»»÷¸ÅÂÊ
def GetFujiaHitRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FujiaHitRate)
def SetFujiaHitRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_FujiaHitRate, 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)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_BleedDamage, value, False)
    
## ×îÖչ̶¨É˺¦Ôö¼Ó
def GetFinalHurt(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurt)
def SetFinalHurt(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurt, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_FinalHurt, value, False)
## ×îÖչ̶¨É˺¦¼õÉÙ
def GetFinalHurtReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_FinalHurtReduce)
def SetFinalHurtReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_FinalHurtReduce, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_FinalHurtReduce, value, False)
## ¶ÔÖ¸¶¨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 GetHorcruxBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorcruxBasePer)
def SetHorcruxBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorcruxBasePer, value)
# ×°±¸»ù´¡°Ù·Ö±È
def GetEquipBaseAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_EquipBaseAddPer)
def SetEquipBaseAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_EquipBaseAddPer, value)
# ÎäÆ÷»ù´¡¹¥»÷°Ù·Ö±È
def GetWeaponAtkAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WeaponAtkAddPer)
def SetWeaponAtkAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WeaponAtkAddPer, value)
# Ê¥Æ÷»ù´¡¹¥»÷°Ù·Ö±È
def GetRelicsAtkAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RelicsAtkAddPer)
def SetRelicsAtkAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_RelicsAtkAddPer, value)
# ·À¾ß»ù´¡ÉúÃü°Ù·Ö±È
def GetArmorMaxHPAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ArmorMaxHPAddPer)
def SetArmorMaxHPAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_ArmorMaxHPAddPer, value)
# ·À¾ß»ù´¡·ÀÓù°Ù·Ö±È
def GetArmorDefAddPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ArmorDefAddPer)
def SetArmorDefAddPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_ArmorDefAddPer, 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)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_OnlyFinalHurt, value, False)
    return
# PVP¹¥»÷»ØÑª
def GetPVPAtkBackHP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PVPAtkBackHP)
def SetPVPAtkBackHP(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PVPAtkBackHP, value)
# ÃüÖгɹ¦ÂÊ
def GetHitSucessRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HitSucessRate)
def SetHitSucessRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HitSucessRate, value)
# ÉÁ±Ü³É¹¦ÂÊ
def GetMissSucessRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MissSucessRate)
def SetMissSucessRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_MissSucessRate, value)
# ÖÎÁÆ¼Ó³É Ä¬ÈϰٷְÙ
def GetCurePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CurePer)
def SetCurePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_CurePer, value)
# ¼ÓÉîÊܵ½É˺¦°Ù·Ö±È
def GetBeHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_BeHurtPer)
def SetBeHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_BeHurtPer, value)
# ×øÆï¹¥»÷°Ù·Ö±È
def GetHorseAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_HorseAtkPer)
def SetHorseAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_HorseAtkPer, value)
# ±¦Ê¯»ù´¡ÊôÐÔ°Ù·Ö±È
def GetStoneBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_StoneBasePer)
def SetStoneBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_StoneBasePer, value)
# ¾³½ç»ù´¡ÊôÐÔ°Ù·Ö±È
def GetRealmBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_RealmBasePer)
def SetRealmBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_RealmBasePer, value)
# ³á°òÉúÃü°Ù·Ö±È
def GetWingHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_WingHPPer)
def SetWingHPPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_WingHPPer, value)
# Ì××°»ù´¡ÊôÐÔ°Ù·Ö±È
def GetSuiteBasePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SuiteBasePer)
def SetSuiteBasePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_SuiteBasePer, value)
# Ç¿»¯»ù´¡¹¥»÷°Ù·Ö±È
def GetPlusBaseAtkPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PlusBaseAtkPer)
def SetPlusBaseAtkPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PlusBaseAtkPer, value)
## ÔÝÎÞÓÃ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return 
def GetAddBackHPPer(curPlayer):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AddBackHPPer)
## ÔÝÎÞÓÃ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return None
def SetAddBackHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AddBackHPPer, value)
    
#---½µµÍÉúÃü»Ö¸´Ð§¹û----
## »ñÈ¡½µµÍÉúÃü»Ö¸´Ð§¹ûÍò·ÖÂÊ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return 
def GetReduceBackHPPer(curPlayer):
    return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ReduceBackHPPer)
## ÉèÖýµµÍÉúÃü»Ö¸´Ð§¹ûÍò·ÖÂÊ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return None
def SetReduceBackHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ReduceBackHPPer, value)
#---´¥·¢»÷ÔÎ----
def GetFaintRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrFaintRate)
def SetFaintRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrFaintRate, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_FaintRate, value, False)
#---»÷Ôεֿ¹----
def GetFaintDefRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrFaintDefRate)
def SetFaintDefRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrFaintDefRate, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_FaintDefRate, value, False)
#---´¥·¢¶¨Éí----
def GetAtkerFreezed(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrAtkerFreezed)
def SetAtkerFreezed(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrAtkerFreezed, value)
    
#---Ôö¼Ó³ðºÞ----
def GetAddAngry(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrAddAngry)
def SetAddAngry(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrAddAngry, value)
#---Á¬»÷¼¸ÂÊ----
def GetComboRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrComboRate)
def SetComboRate(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrComboRate, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ComboRate, value, False)
#---Á¬»÷É˺¦----
def GetComboDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrComboDamPer)
def SetComboDamPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrComboDamPer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ComboDamPer, value, False)
    
#---¼¼Äܹ¥»÷±ÈÀý¼õÉÙ----
def GetSkillAtkRateReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_SkillAtkRateReduce)
def SetSkillAtkRateReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_SkillAtkRateReduce, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_SkillAtkRateReduce, value, False)
#---É˺¦Êä³ö¼ÆËã°Ù·Ö±È----
def GetDamagePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePer)
def SetDamagePer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_DamagePer, value, False)
#---É˺¦Êä³ö¼ÆËã°Ù·Ö±È¶ÔNPC¸½¼Ó----
def GetDamagePerPVE(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePerPVE)
def SetDamagePerPVE(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePerPVE, value)
#---É˺¦Êä³ö¼ÆËã°Ù·Ö±È¶ÔÍæ¼Ò¸½¼Ó----
def GetDamagePerPVP(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePerPVP)
def SetDamagePerPVP(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePerPVP, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_DamagePerPVP, value, False)
def GetDamagePerPVPReduce(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamagePerPVPReduce)
def SetDamagePerPVPReduce(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamagePerPVPReduce, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_DamagePerPVPReduce, value, False)
    
#---ÊÜÉ˼ÆËã°Ù·Ö±È----
def GetHurtPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrHurtPer)
def SetHurtPer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrHurtPer, value)
  
#---×Ô¶¯»Ö¸´XPÖµ±ÈÂÊ----
def GetXPRestorePer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrXPRestorePer)
def SetXPRestorePer(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrXPRestorePer, value)
#---ħ·¨¶ÜÉ˺¦ÎüÊÕÀ¶ºÄ±ÈÂÊ----
def GetShieldMPCostRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrShieldMPCostRate)
def SetShieldMPCostRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrShieldMPCostRate, value)
  
#---20%µÄ¸ÅÂʵÖÓùÉ˺¦±ÈÂÊ----
def GetDamChanceDef(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrDamChanceDef)
def SetDamChanceDef(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrDamChanceDef, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_DamChanceDef, value, False)
    
#---µ±Ç°·À»¤Öµ£¬Ðè´æDB----
def GetProDef(curPlayer): return curPlayer.GetExAttr4()
def SetProDef(curPlayer, value): curPlayer.SetExAttr4(value)
#---×î´ó·À»¤Öµ----
def GetMaxProDef(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrMaxProDef)
def SetMaxProDef(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrMaxProDef, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_MaxProDef, value, True) # ÖÜÎ§Íæ¼ÒÐèҪ֪ͨ
#---ÉúÃüÉÏÏÞ»»ËãΪ·À»¤ÖµµÄ°Ù·Ö±È----
def GetProDefHPPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefHPPer)
def SetProDefHPPer(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefHPPer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefHPPer, value, False)
#---·À»¤ÖµÎüÊÕÉ˺¦±ÈÂÊ----
def GetProDefAbsorb(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrProDefAbsorb)
def SetProDefAbsorb(curPlayer, value):
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrProDefAbsorb, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ProDefAbsorb, value, False)
    
#---³èÎï¹¥»÷ÌáÉýÖµ----
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)
#---³èÎïÉ˺¦°Ù·Ö±ÈÌáÉý----
def GetPetDamPer(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_AttrPetDamPer)
def SetPetDamPer(curPlayer, value): 
    curPlayer.SetDict(ChConfig.Def_PlayerKey_AttrPetDamPer, value)
    curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_PetDamPer, value, False)
#---³èÎï¼¼ÄÜÉ˺¦°Ù·Ö±ÈÌáÉý----
def GetPetSkillAtkRate(curPlayer): return curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PetSkillAtkRate)
def SetPetSkillAtkRate(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_PetSkillAtkRate, value)
    
#---ÿ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 curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CopyFuncAttr % (ChConfig.TYPE_Calc_AttrDEF - 1))
def SetFuncDef(curPlayer, value): curPlayer.SetDict(ChConfig.Def_PlayerKey_CopyFuncAttr % (ChConfig.TYPE_Calc_AttrDEF - 1), value)
## Ôö¼ÓÌìÌݾº¼¼³¡»ý·Ö
#  @param curPlayer Íæ¼ÒʵÀý
#  @return
def AddHighLadderCurrency(curPlayer, addCount, isSysMsg=True, isRefresh=True):
    curCurrency = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HighLadder_Currency)
    curCurrency += addCount
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HighLadder_Currency, curCurrency)
    
    if isSysMsg:
        #֪ͨ¿Í»§¶ËµÃµ½½ðÇ®
        NotifyCode(curPlayer, "GetMoney", [ShareDefine.TYPE_Price_HighLadder_Currency, addCount])
    if isRefresh:
        tick = GameWorld.GetGameWorld().GetTick()
        HighLadderTube.SendHighLadderState(curPlayer, tick)
    return
## ÓÃÌìÌݾº¼¼³¡»ý·Ö¸¶·Ñ
#  @param curPlayer Íæ¼ÒʵÀý
#  @return
def PayHighLadderCurrency(curPlayer, payCount, isSysMsg=True, isRefresh=True):
    curCurrency = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HighLadder_Currency)
    if (curCurrency < payCount) or (payCount < 0):
        return False, curCurrency, curCurrency
    updCurrency = max(0, curCurrency - payCount)
    NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_HighLadder_Currency, updCurrency)
    if isSysMsg:
        #֪ͨ¿Í»§¶ËʧȥµãÊý
        NotifyCode(curPlayer, "LostMoney", [ShareDefine.TYPE_Price_HighLadder_Currency, payCount]) 
    if isRefresh:
        tick = GameWorld.GetGameWorld().GetTick()
        HighLadderTube.SendHighLadderState(curPlayer, tick)   
    return True, curCurrency, updCurrency
## ¼ÆË㹦Äܱ³°üÎïÆ·ÊôÐÔ 
#  @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_MaxAddAttrTypeCnt*2¸öÁÙʱ×ֵ仺´æ(Ò»¸ö´æÀàÐÍ£¬Ò»¸ö´æÖµ)
Def_MaxAddAttrTypeCnt = 15
# ͨ¹ýSetCalcAttrListValueÏÈ»º´æ¹¦ÄܼÆËãÔö¼ÓµÄÊôÐÔÖµ£¬½öÔÚ±ä¸üÊ±ÖØÐ¼ÆËãÉèÖÃ
# ͨ¹ýAddCalcAttrListValueÈ¡³ö»º´æÖÐÒѾËãºÃµÄÊôÐÔÖµ£¬ÔÚË¢ÊôÐÔÖнøÐÐÀÛ¼Ó£¬´Ó¶ø¼õÉÙÿ´ÎÖØÐ¼ÆË㹦ÄÜÔö¼ÓµÄÊôÐÔ
## ÉèÖñ£´æ¹¦ÄÜÊÂÏȼÆËãºÃµÄÊôÐÔÖµ
def SetCalcAttrListValue(curPlayer, funcIndex, allAttrList):
    # ÉèÖÃֵ֮ǰÏÈÇå¿ÕÖØÖÃ
    ClearCalcAttrListValue(curPlayer, funcIndex)
    
    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
        
    for attrIndex, addAttrDict in enumerate(allAttrList):
        findIndex = -1
        for attrType, attrValue in addAttrDict.items():
            if not isinstance(attrValue, int):
                GameWorld.ErrLog("SetCalcAttrListValue funcIndex=%s,attrType=%s,Value=%s is not int!" 
                                 % (funcIndex, attrType, attrValue), curPlayer.GetPlayerID())
                continue
            for i in xrange(findIndex + 1, Def_MaxAddAttrTypeCnt):
                addAttrTypeKey = ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i)
                addAttrValueKey = ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i)
                if curPlayer.GetDictByKey(addAttrTypeKey) == 0:
                    findIndex = i
                    curPlayer.SetDict(addAttrTypeKey, attrType)
                    curPlayer.SetDict(addAttrValueKey, attrValue)
                    break
    return
def GetCalcAttrListValue(curPlayer, funcIndex):
    ## »ñÈ¡¹¦ÄܵãÔ¤ÏȼÆËãµÄËù¼ÓÊôÐÔÖµ
    attrList = [{} for _ in range(4)]
    for attrIndex, attrDict in enumerate(attrList):
        for i in xrange(Def_MaxAddAttrTypeCnt):
            attrType = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i))
            if attrType == 0:
                break
            attrDict[attrType] = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i))
    return attrList
## Ë¢ÊôÐÔʱÀÛ¼Ó¹¦ÄÜÊÂÏȼÆËãºÃµÄÊôÐÔÖµ
def AddCalcAttrListValue(curPlayer, funcIndex, allAttrList):
    for attrIndex in ChConfig.CalcAttrIndexList:
        for i in xrange(Def_MaxAddAttrTypeCnt):
            curAddAttrType = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i))
            if curAddAttrType == 0:
                break
            curAddAttrValue = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i))
            addAttrDict = allAttrList[attrIndex]
            AddAttrDictValue(addAttrDict, {curAddAttrType:curAddAttrValue})
            
    return allAttrList
## ÖØÖûº´æ
def ClearCalcAttrListValue(curPlayer, funcIndex):
    for attrIndex in ChConfig.CalcAttrIndexList:
        for i in xrange(Def_MaxAddAttrTypeCnt):
            addAttrTypeKey = ChConfig.Def_PlayerKey_CalcAddAttrType % (funcIndex, attrIndex, i)
            attrType = curPlayer.GetDictByKey(addAttrTypeKey)
            if not attrType:
                break
            curPlayer.SetDict(addAttrTypeKey, 0)
            curPlayer.SetDict(ChConfig.Def_PlayerKey_CalcAddAttrValue % (funcIndex, attrIndex, i), 0)
    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 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