| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package GameWorld  | 
| # @todo: ¹«Óú¯Êýµ÷Óà  | 
| #  | 
| # @author PanWei  | 
| # @date 2010-5-2 09:56:54  | 
| # @version 3.3  | 
| #  | 
| # @change: "2013-03-06 17:30" Alee CanHappenº¯ÊýÌí¼ÓĬÈÏÖµ  | 
| # @change: "2013-03-20 18:00" Alee Ìí¼ÓDebugLogº¯Êý  | 
| # @change: "2013-04-17 20:35" Alee Ìí¼ÓÁ½¸ö×Öµä¼Ó·¨º¯Êý  | 
| # @change: "2013-04-23 16:00" wdb ×°±¸µôÂä  | 
| # @change: "2013-06-03 14:00" wdb Ëæ»úº¯Êý¼ÓĬÈÏÖµ  | 
| # @change: "2013-06-19 19:55" Alee Á½µã¼äÕϰµãº¯ÊýÒÑÓÐCanLineTo  | 
| # @change: "2013-06-24 21:00" Alee Ð޸ľØÕóÐýת±ÜÃâ²úÉú©µã   | 
| # @change: "2013-07-05 17:00" wdb Ôö¼Óº¯Êý£¬Ê¹ÓÃÊýλÉèÖÃÐÅÏ¢   | 
| # @change: "2013-08-05 15:30" hxp Ð޸ĻñÈ¡·þÎñÆ÷ϵͳʱ¼ä·½Ê½   | 
| # @change: "2013-08-23 16:00" Alee ¾ØÕó¼ÆËãÐÞ¸Ä  | 
| # @change: "2013-09-06 14:00" hxp ÐÞ¸ÄÖ¸¶¨¸ÅÂÊÁбíת»¯Îª±ýͼÁбíËã·¨  | 
| # @change: "2013-09-10 20:10" Alee ¾ØÕ󰴽ǶÈÐýתÐÞ¸Ä  | 
| # @change: "2013-12-06 15:30" Alee Ð޸ĸÅÂÊÁÐ±í¼ÆËã·½·¨  | 
| # @change: "2014-02-14 21:43" xmnathan ¸ÅÂʱýͼ¼ÓÈëÁÙ½çÖµ¹éÊô²ÎÊý£¬Ä¬ÈϹéÊôǰһ¸öË÷ÒýÇøÓò  | 
| # @change: "2014-12-28 21:00" hxp Ôö¼Ó»ñȡƽ̨¼°·þÎñÆ÷ID  | 
| # @change: "2015-01-07 19:00" hxp Ôö¼Ó¿ÉÉèÖÃ×î´ó±ýͼ¸ÅÂʺ¯Êý  | 
| # @change: "2015-01-14 00:30" hxp Ôö¼Ó»ñÈ¡Íæ¼Ò³õÊ¼Çø·þID  | 
| # @change: "2015-03-05 14:00" ljd Ôö¼ÓÔö³¤Áбí(±ýͼ)¿ÉËæ»ú¶à¸öÐÅÏ¢(·ÇÖØ¸´)  | 
| # @change: "2015-06-08 20:30" hxp Ôö¼Ó»ñÈ¡Íæ¼ÒchannelCode  | 
| # @change: "2015-09-18 19:30" hxp Ôö¼Ó¹ã²¥×Ó·þ£»Ôö¼Ó°´ÅÅÃû×Öµä»ñÈ¡Ãû´Î¶ÔÓ¦Öµ  | 
| # @change: "2015-09-21 20:30" hxp Ôö¼Ó×Ô¶¨Òå»õ±ÒÖµ»ñÈ¡  | 
| # @change: "2015-10-10 10:10" hxp Ôö¼Ó»ñÈ¡Íæ¼Ò³õÊ¼Çø·þID£¬²»´øs  | 
| # @change: "2015-10-22 23:00" hxp Ôö¼ÓSendMergerChildToCenterStringData  | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2015-10-22 23:00"""  | 
| #---------------------------------------------------------------------  | 
| import IPY_GameWorld  | 
| import LogUI  | 
| import ReadChConfig  | 
| import random  | 
| import math  | 
| import sys  | 
| import datetime  | 
| import ChConfig  | 
| import os  | 
| import MapConfig  | 
| import CommFunc  | 
| import ShareDefine  | 
| import PyMapTable  | 
| #import psyco  | 
| from decimal import Decimal  | 
| import time  | 
| import copy  | 
| import ConfigParser  | 
|   | 
| import md5  | 
| #---------------------------------------------------------------------  | 
| #ÉèÖÃÔÊÐíµÄ×î´óµü´úÊýÄ¿, Ä¬ÈÏ1000  | 
| #ÔÚNPCAIÖÐ, ¿ÉÄܳ¬¹ý1000, ËùÒÔÒªÉ趨Ϊ2000  | 
| sys.setrecursionlimit(2000)  | 
| #-----------------------------------------------  | 
|   | 
| ServerRootPath = "" # ·þÎñÆ÷¸ù·¾¶  | 
| MergeServerID = 0 # ±¾×Ó·þµÄ¿ç·þID  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##µ¼ÈëPy½Å±¾  | 
| # @param pathDir ÏîĿ·¾¶  | 
| # @param importDir µ¼ÈëµÄ½Å±¾Â·¾¶  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks µ¼ÈëPy½Å±¾  | 
| def ImportAll(pathDir, importDir):  | 
|     scriptPath = ChConfig.GetAppPath() + pathDir + importDir  | 
|       | 
|     fileNameList = __GetFuncFileNameList(scriptPath)  | 
|       | 
|     for fileName in fileNameList:  | 
|         #»ñµÃ¼ÓÔØµÄ·¾¶  | 
|         importPath = __GetSysModulesScriptPath(importDir, fileName)  | 
|           | 
|         #²»Öظ´¼ÓÔØ  | 
|         if sys.modules.has_key(importPath):  | 
|             continue  | 
|           | 
|         __import__(importPath)  | 
|       | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ##ÖØÐ¼ÓÔØ½Å±¾.  | 
| # @param scriptPath ½Å±¾Â·¾¶  | 
| # @param importDir µ¼ÈëµÄ½Å±¾Â·¾¶  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ÖØÐ¼ÓÔØ½Å±¾  | 
| def ReloadScript(scriptPath, importDir):  | 
|     gameWorld = GetGameWorld()  | 
|     tick = gameWorld.GetTick()  | 
|       | 
|     #δµ½Ë¢Ð¼ä¸ô  | 
|     if tick - gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript) < \  | 
|                 ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_ReloadScript]:  | 
|         return  | 
|       | 
|     gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript, tick)  | 
|       | 
|     if __GetPsycoIsOpen():  | 
|         #Psyco¿ªÆô  | 
|         PsycoReload(tick)  | 
|         return  | 
|   | 
|     #Psyco¹Ø±Õ  | 
|     __ReloadScript()  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÖØ¶Á½Å±¾  | 
| # @param ÎÞ²ÎÊý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks   | 
| def __ReloadScript():  | 
|     #ÖØÐ¼ÓÔØÒѾԤ´æµÄ½Å±¾  | 
|     for name, reloadPath in sys.modules.items():  | 
|         try:  | 
|             if name in ["PyGameData"]:  | 
|                 DebugLog("%s Ä£¿é²»ÖضÁ!" % name)  | 
|                 continue  | 
|             reload(reloadPath)  | 
|         except Exception:  | 
|             continue  | 
|   | 
|     Log("Reload Begin : time = %s"%GetCurrentDataTimeStr())  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ·¾¶ÏµÄÎļþÁÐ±í  | 
| # @param scriptPath ½Å±¾Â·¾¶  | 
| # @return ÎļþÁÐ±í  | 
| # @remarks »ñµÃ·¾¶ÏµÄÎļþÁÐ±í  | 
| def __GetFuncFileNameList(scriptPath):  | 
|     fileNameList = []  | 
|       | 
|     if not os.path.isdir(scriptPath):  | 
|         ErrLog('ReloadScript Err, path = %s is not dir'%(scriptPath))  | 
|         return fileNameList  | 
|       | 
|     filesList = os.listdir(scriptPath)  | 
|       | 
|     for file in filesList:  | 
|         #Óõã·Ö¸î  | 
|         fileStruct = file.split(".")  | 
|           | 
|         #Õâ¸öÊÇĿ¼»òÕß²»ÊǺϷ¨Îļþ, Èçxx.py  | 
|         if len(fileStruct) != 2:  | 
|             continue  | 
|           | 
|         fileName, fileExt = fileStruct  | 
|           | 
|         if fileName.find("__init__") >= 0:  | 
|             continue  | 
|           | 
|         if fileExt not in ChConfig.TYPE_Load_Module_Ext:  | 
|             continue  | 
|           | 
|         fileNameList.append(fileName)  | 
|           | 
|     return fileNameList  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÔ¤¼ÓÔØµÄ½Å±¾Â·¾¶.  | 
| # @param importDir µ¼Èë·¾¶  | 
| # @param fileName ÎļþÃû  | 
| # @return Ô¤¼ÓÔØµÄ½Å±¾Â·¾¶  | 
| # @remarks »ñµÃÔ¤¼ÓÔØµÄ½Å±¾Â·¾¶.  | 
| def __GetSysModulesScriptPath(importDir, fileName):  | 
|     sysModulesPath = fileName  | 
|           | 
|     if importDir != "":  | 
|         sysModulesPath = importDir + '.' + fileName  | 
|               | 
|     return sysModulesPath  | 
| #---------------------------------------------------------------------  | 
| ##A/B ÏòÉÏÈ¡Õû  | 
| # @param x ÊäÈëµÄÊý  | 
| # @param div ³ýÊý  | 
| # @return ·µ»ØÖµ, ÏòÉÏÈ¡ÕûºóµÄÖµ  | 
| # @remarks A/B ÏòÉÏÈ¡Õû  | 
| def GetIntUpper(x, div):  | 
|     return int(math.ceil(x / float(div)))  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¸¡µãÊýÏòÉÏÈ¡Õû  | 
| # @param x ÊäÈëµÄÊý  | 
| # @return ·µ»ØÖµ, ÏòÉÏÈ¡ÕûºóµÄÖµ  | 
| # @remarks ¸¡µãÊýÏòÉÏÈ¡Õû  | 
| def GetFloatUpper(x):  | 
|     return int(math.ceil(x))  | 
|   | 
| #---------------------------------------------------------------------  | 
| #¾¯¸æ£º1.ЧÂʵÍÏ£¬²»½¨ÒéʹÓà  | 
| #     2.Êý×ÖתstrÇë½÷É÷ʹÓã¬Ð§¹û»áÓвîÒì  | 
| ##¸ß¾«¶È¸¡µãÊýÏòÉÏÈ¡Õû, ¾¯¸æ£ºÐ§ÂʵÍÏ£¬²»½¨ÒéʹÓà  | 
| # @param x ÊäÈëµÄÊý  | 
| # @return ·µ»ØÖµ, ÏòÉÏÈ¡ÕûºóµÄÖµ  | 
| # @remarks ¸¡µãÊýÏòÉÏÈ¡Õû  | 
| #def GetDecimalFloatUpper(x):  | 
| #    #ÒòPsyco½«Decimal('%s'%(x))·µ»ØÖµµ±³ÉÀà¶ÔÏó´¦Àí, µ¼ÖÂceil±¨´í, ÐèҪת»»³É¸¡µã  | 
| #    return int(math.ceil(float(Decimal(str(x)))))  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ¸¡µãËæ»úÊý  | 
| # @param minX ×îСÊý  | 
| # @param maxX ×î´óÊý  | 
| # @param precis ·Å´ó»ùÊý  | 
| # @return ·µ»ØÖµ, Öµ  | 
| # @remarks »ñµÃ¸¡µãËæ»úÊý  | 
| def GetFloatRan(minX, maxX, precis = 2):  | 
|     #±¶ÂÊ  | 
|     multiple = pow(10, precis)  | 
|     ran = random.randint(minX + 1, maxX * multiple - 1)  | 
|     return ran / float(multiple)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##È¡µÃ·½Ïò, ·µ»Ø½Ç¶ÈÖµ  | 
| # @param StartX ÆðµãX  | 
| # @param StartY ÆðµãY  | 
| # @param EndX ÖÕµãX  | 
| # @param EndY ÖÕµãY  | 
| # @return ·µ»Ø½Ç¶ÈÖµ  | 
| # @remarks È¡µÃ·½Ïò, ·µ»Ø½Ç¶ÈÖµ  | 
| def GetAngle(StartX, StartY, EndX, EndY):  | 
|     #µÃµ½´Ó(StartX, StartY)µ½(EndX, EndY)µÄ½Ç¶È  | 
|     if StartX == EndX and StartY == EndY:  | 
|         #ûÓз½Ïò  | 
|         return 0  | 
|       | 
|     rad = math.atan2(EndY - StartY, EndX - StartX)  | 
|     th = int(math.degrees(rad))  | 
|     if th < 0:  | 
|         th = th + 360  | 
|           | 
|     return th  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¾ØÕóÐýת  | 
| # @param matrix ÔÁÐ±í  | 
| # @param playerX Íæ¼Ò×ø±êX  | 
| # @param playerY Íæ¼Ò×ø±êY  | 
| # @param destX Ä¿±ê×ø±êX  | 
| # @param destY Ä¿±ê×ø±êY  | 
| # @return ·µ»Ø, ¾ØÕóÐýתºóµÄÁÐ±í  | 
| # @remarks ¾ØÕóÐýת  | 
| #===============================================================================  | 
| # def MatrixCircle(matrix, playerX, playerY, destX, destY):  | 
| #    result = list()  | 
| #    dist = math.sqrt(math.pow((playerX-destX), 2)+math.pow((playerY-destY), 2))  | 
| #      | 
| #    cos = 1.0  | 
| #    sin = 0.0  | 
| #      | 
| #    if dist != 0:  | 
| #        cos = (destX-playerX)/dist  | 
| #        sin = (destY-playerY)/dist  | 
| #    for i in range(0, len(matrix)):  | 
| #        x = FiveInOtherOut(matrix[i][0]*cos-matrix[i][1]*sin)  | 
| #        y = FiveInOtherOut(matrix[i][1]*cos+matrix[i][0]*sin)  | 
| #        curPos = (x, y)  | 
| #          | 
| #        if curPos in result:  | 
| #            continue  | 
| #        result.append(curPos)  | 
| #          | 
| #    return result  | 
| #   | 
| # #---------------------------------------------------------------------  | 
| # ##»ñµÃ½Ç¶È  | 
| # # @param num ½Ç¶ÈÖµ  | 
| # # @return ·µ»ØÖµ, ½Ç¶È  | 
| # # @remarks »ñµÃ½Ç¶È  | 
| # def FiveInOtherOut(num):  | 
| #    #»á²úÉú©¶´  | 
| #    #===========================================================================  | 
| #    # value = num - int(num)  | 
| #    # if value == 0.5:  | 
| #    #    return int(num)  | 
| #    # elif value == 0.4:  | 
| #    #    return int(num)+ 1  | 
| #    # elif value > 0.5:  | 
| #    #    return int(num) + 1  | 
| #    #===========================================================================  | 
| #      | 
| #    return int(num)  | 
| #===============================================================================  | 
|        | 
| ##¾ØÕóÐýת  | 
| # @param matrix ÔÁÐ±í  | 
| # @param playerX Íæ¼Ò×ø±êX  | 
| # @param playerY Íæ¼Ò×ø±êY  | 
| # @param destX Ä¿±ê×ø±êX  | 
| # @param destY Ä¿±ê×ø±êY  | 
| # @return ·µ»Ø, ¾ØÕóÐýתºóµÄÁÐ±í  | 
| # @remarks ¾ØÕóÐýת  | 
| def MatrixCircle(matrix, playerX, playerY, destX, destY):  | 
|     result = list()  | 
|     dist = math.sqrt(math.pow((playerX - destX), 2) + math.pow((playerY - destY), 2))  | 
|       | 
|     cos = 1.0  | 
|     sin = 0.0  | 
|       | 
|     if dist != 0:  | 
|         cos = (destX-playerX)/dist  | 
|         sin = (destY-playerY)/dist  | 
|           | 
|     for i in range(0, len(matrix)):  | 
|         xlist = FiveInOtherOut(matrix[i][0]*cos-matrix[i][1]*sin)  | 
|         ylist = FiveInOtherOut(matrix[i][1]*cos+matrix[i][0]*sin)  | 
|         for curPos in GetAllPos(xlist, ylist):  | 
|           | 
|             if result.count(curPos) != 0:  | 
|                 continue  | 
|             result.append(curPos)  | 
|           | 
|     if [0, 0] in matrix and (0, 0) not in result:  | 
|         result.insert(0, (0, 0))  | 
|           | 
|     return result  | 
|   | 
| # ¸ù¾Ý¾àÀëÕÒÁ½µã¼äÖ±ÏßÉϵĵ㣬ÒÔÖÕµãΪԵãÆðµãΪ·½Ïò£¬¾àÀëÖÕµãposDist¾àÀëµÄµã  | 
| def PosInLineByDist(posDist, destX, destY, posX, posY):  | 
|     dist = math.sqrt(math.pow((destX - posX), 2) + math.pow((destY - posY), 2))  | 
|     cos = 1.0  | 
|     sin = 0.0  | 
|       | 
|     if dist != 0:  | 
|         cos = (posX-destX)/dist  | 
|         sin = (posY-destY)/dist  | 
|   | 
|     resultX = int(cos*posDist + destX)  | 
|     resultY = int(sin*posDist + destY)  | 
|           | 
|     return resultX, resultY  | 
|   | 
| # Ö±ÏßÉÏ£¬ÒÔÆðµãΪԵ㣬ÖÕµãΪ·½Ïò£¬¾àÀëÆðµãposDistµÄµã  | 
| def PosInLineByDistEx(posDist, destX, destY, posX, posY):  | 
|     dist = math.sqrt(math.pow((destX - posX), 2) + math.pow((destY - posY), 2))  | 
|     cos = 1.0  | 
|     sin = 0.0  | 
|       | 
|     if dist != 0:  | 
|         cos = (posX-destX)/dist  | 
|         sin = (posY-destY)/dist  | 
|   | 
|     resultX = int(posX - cos*posDist)  | 
|     resultY = int(posY - sin*posDist)  | 
|           | 
|     return resultX, resultY  | 
|   | 
|   | 
|   | 
|   | 
| ##¸½¼Ó»ñµÃ°ë¸ñÒÔÉϵĸ²¸Çµã  | 
| # @param num ½Ç¶ÈÖµ  | 
| # @return ¿ÉÄÜ´æÔڵĵãÁÐ±í  | 
| def FiveInOtherOut(num):  | 
|     num1 = int(num)  | 
|     num2 = int(MyRound(num))  | 
|     if num1 == num2:  | 
|         return [num1]  | 
|     return [num1, num2]  | 
|   | 
|   | 
| ## ×éºÏ³É×ø±êµã  | 
| #  @param None  | 
| #  @return None  | 
| def GetAllPos(xlist, ylist):  | 
|     poslist = []  | 
|     for x in xlist:  | 
|         for y in ylist:  | 
|             poslist.append((x, y))  | 
|   | 
|     return poslist  | 
|   | 
|               | 
| #---------------------------------------------------------------------  | 
| ##È¡µÃ°Ù·Ö±È  | 
| # @param value »ù´¡Öµ  | 
| # @param percent °Ù·Ö±È  | 
| # @return ·µ»ØÖµ, ½Ç¶È  | 
| # @remarks È¡µÃ°Ù·Ö±È  | 
| def GetPercent(value, percent):  | 
|     return value * percent / 100  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##×Ö·û´®×ª»»ÎªÕûÐÍ, Èç¹û²»ÄÜת»», ·µ»ØÄ¬ÈÏÖµ  | 
| # @param input ÊäÈëÖµ  | 
| # @param defValue Ä¬ÈÏÖµ  | 
| # @return ·µ»ØÖµ, ×ª»»ºóµÄÖµ  | 
| # @remarks ×Ö·û´®×ª»»ÎªÕûÐÍ, Èç¹û²»ÄÜת»», ·µ»ØÄ¬ÈÏÖµ  | 
| def ToIntDef(input, defValue = 0):  | 
|     try:  | 
|         result = int(input)  | 
|         return result  | 
|     except ValueError:  | 
|         return defValue  | 
|   | 
| ##½«Êý×ÖÏÞÖÆÔÚij¸ö·¶Î§  | 
| # @param input ÊäÈëÖµ  | 
| # @param minNum ×îСֵ  | 
| # @param maxNum ×î´óÖµ  | 
| # @return ÏÞÖÆºóµÄÖµ  | 
| # @remarks ½«Êý×ÖÏÞÖÆÔÚij¸ö·¶Î§  | 
| def ToIntArea(input, minNum, maxNum):  | 
|     return int(min(max(input, minNum), maxNum))  | 
|       | 
| #---------------------------------------------------------------------  | 
| ##ͨ¹ýµ÷ÓÃÃû³Æ»ñÈ¡µ÷ÓÃʵÀý  | 
| # @param curCallObj º¯Êý¶ÔÏó  | 
| # @param callName º¯ÊýÃû  | 
| # @return ·µ»ØÖµ, º¯ÊýʵÀý  | 
| # @remarks º¯Êýµ÷Óà  | 
| def ParseNameGetObj(curCallObj, callName):  | 
|     callList = callName.split(".")  | 
|     if len(callList) <= 1:  | 
|         return None  | 
|       | 
|     for curCallName in callList:  | 
|         if hasattr(curCallObj, curCallName) != True:  | 
|             #ÎÞ´ËÊôÐÔ  | 
|             return None  | 
|           | 
|         curCallObj = getattr(curCallObj, curCallName)  | 
|           | 
|     return curCallObj  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Ö´Ðк¯Êýµ÷Óà  | 
| # @param curCallObj º¯Êý¶ÔÏó  | 
| # @param callName º¯ÊýÃû  | 
| # @return ·µ»ØÖµ, º¯ÊýʵÀý  | 
| # @remarks Ö´Ðк¯Êýµ÷Óà  | 
| def GetExecFunc(curCallObj, callName):  | 
|     curCallObj = ParseNameGetObj(curCallObj, callName)  | 
|     if curCallObj == None:  | 
|         return None  | 
|           | 
|     if callable(curCallObj) != True:  | 
|         #²»¿Éµ÷Óà  | 
|         return None  | 
|       | 
|     return curCallObj  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¼ì²éÊÇ·ñÂúÄ;à  | 
| # @param curItem Íæ¼ÒʵÀý  | 
| # @return ·µ»ØÖµ, ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ¼ì²éÊÇ·ñÂúÄ;à  | 
| def CheckItemIsMaxEndure(curItem):  | 
|     return True  | 
|     #===========================================================================  | 
|     # curItemCurDurg = GetIntUpper(curItem.GetCurDurg(), ChConfig.Def_EndureRepairParameter)  | 
|     # curItemMaxEndure = curItem.GetMaxEndure() / ChConfig.Def_EndureRepairParameter  | 
|     # return curItemCurDurg == curItemMaxEndure  | 
|     #===========================================================================  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ2µã¼ä¾àÀë  | 
| # @param posX ÆðµãX  | 
| # @param posY ÆðµãY  | 
| # @param tagX Ä¿±êX  | 
| # @param tagY Ä¿±êY  | 
| # @return ·µ»ØÖµ, ¾àÀë  | 
| # @remarks »ñµÃ2µã¼ä¾àÀë  | 
| def GetDist(posX, posY, tagX, tagY):  | 
|     return max(abs(posX - tagX), abs(posY - tagY))  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ2µã¼ä¾àÀë(¹´¹É¶¨Àí)  | 
| # @param posX ÆðµãX  | 
| # @param posY ÆðµãY  | 
| # @param tagX Ä¿±êX  | 
| # @param tagY Ä¿±êY  | 
| # @return ·µ»ØÖµ, ¾àÀë  | 
| # @remarks »ñµÃ2µã¼ä¾àÀë(¹´¹É¶¨Àí)  | 
| def GetDistEx(posX, posY, tagX, tagY):  | 
|     return GetFloatUpper(math.sqrt(pow(posX - tagX, 2) + pow(posY - tagY, 2)))  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ  | 
| # @param rate »ù´¡¼¸ÂÊ  | 
| # @param maxRate ×î´ó¼¸ÂÊ  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ¸ÅÂÊÏà¹Ø, Õâ¸öʼþÊÇ·ñÄܹ»³öÏÖ  | 
| def CanHappen(rate, maxRate=ShareDefine.Def_MaxRateValue):  | 
|     if random.randint(0, maxRate -1) < rate:  | 
|         return 1  | 
|       | 
|     return 0  | 
|   | 
|   | 
| ## ¸ÅÂÊÏà¹Ø, Ä³¸öʼþÄܹ»³öÏֵĽá¹ûΪ  | 
| # @param rateList ¸÷¸öʼþµÄ¸ÅÂÊ  | 
| # @param maxRate: ×î´ó¸ÅÂÊ  | 
| # @return: ·µ»ØÖµ,ʼþ¸ÅÂʵÄIndex  | 
| def WhichCanHappen(rateList, maxRate):      | 
|     rateList.sort()  | 
|     ranNumber = random.randint(0, maxRate - 1)  | 
|     for number in rateList:  | 
|         if ranNumber > number:  | 
|             continue  | 
|   | 
|         return number  | 
|     return None  | 
|   | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÅжÏ2¸ö¶ÔÏóÊÇ·ñÏàͬ  | 
| # @param srcObj ¶Ô±ÈÄ¿±ê¶ÔÏóA  | 
| # @param desObj ¶Ô±ÈÄ¿±ê¶ÔÏóB  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ÅжÏ2¸ö¶ÔÏóÊÇ·ñÏàͬ  | 
| def IsSameObj(srcObj, desObj):  | 
|     #BUG ÒþÉí·Å¼¼ÄÜ»áA  | 
|     if not srcObj or not desObj:  | 
|         return False  | 
|       | 
|     if srcObj.GetID() == desObj.GetID() and srcObj.GetGameObjType() == desObj.GetGameObjType():  | 
|         return True  | 
|       | 
|     return False  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®  | 
| # @param srcObj ¶Ô±ÈÄ¿±ê¶ÔÏóA  | 
| # @param desObj ¶Ô±ÈÄ¿±ê¶ÔÏóB  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®  | 
| def IsSameCountry(srcObj, desObj):  | 
|     return IsSameCountry_Name(srcObj.GetCountry(), desObj.GetCountry())  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®  | 
| # @param srcName ¶Ô±ÈÄ¿±êÃû×ÖA  | 
| # @param desName ¶Ô±ÈÄ¿±êÃû×ÖB  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¹ú¼®  | 
| def IsSameCountry_Name(srcName, desName):  | 
|     #ͬ¹ú¼®  | 
|     if srcName == desName:  | 
|         return True  | 
|     #ÐÂÊÖ¹ú  | 
|     if srcName == IPY_GameWorld.tcNew or desName == IPY_GameWorld.tcNew:  | 
|         return True  | 
|       | 
|     return False  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¼Ò×å  | 
| # @param srcObj ¶Ô±ÈÄ¿±ê¶ÔÏóA  | 
| # @param desObj ¶Ô±ÈÄ¿±ê¶ÔÏóB  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ÅжÏ2¸ö¶ÔÏóÊÇ·ñͬ¼Ò×å  | 
| def IsSameFamily(srcObj , desObj):  | 
|     srcFamily = srcObj.GetFamilyID()  | 
|     desFamily = desObj.GetFamilyID()  | 
|     if srcFamily == 0 or desFamily == 0:  | 
|         return False  | 
|       | 
|     return srcFamily == desFamily  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¼ì²éÊÇ·ñÊÇGM  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @return ·µ»ØÖµ. ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ¼ì²éÊÇ·ñÊÇGM  | 
| def IsGM(curPlayer):  | 
|     #0:²»ÊÇGM 90:ÄÚ²¿²âÊÔ  | 
|     if curPlayer.GetGMLevel() in [0 , ChConfig.Def_GM_LV_God]:  | 
|         return  | 
|       | 
|     return True  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃµ±Ç°ÏµÍ³Ê±¼ä×Ö·û´®  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ. Ê±¼ä×Ö·û´®  | 
| # @remarks »ñµÃµ±Ç°ÏµÍ³Ê±¼ä×Ö·û´®  | 
| def GetCurrentDataTimeStr():  | 
|     curTime = GetCurrentTime()  | 
|     curTimeStr = str(curTime)  | 
|     curTimeStr = curTimeStr.split(".")[0]  | 
|     return curTimeStr  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ·þÎñÆ÷ϵͳʱ¼ä  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ. Ê±¼äData¸ñʽ  | 
| # @remarks »ñµÃ·þÎñÆ÷ϵͳʱ¼ä  | 
| def GetCurrentTime():  | 
|     return datetime.datetime.today()  | 
| #    ctime = GetGameWorld().GetGameServerEventTime()  | 
| #      | 
| #    if not ctime:  | 
| #        return datetime.datetime.today()  | 
| #      | 
| #    returnTime = GetDateTimeByStr(ctime)  | 
| #      | 
| #    if not returnTime:  | 
| #        returnTime = datetime.datetime.today()  | 
| #          | 
| #    return returnTime  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃϵͳʱ¼ä  | 
| # @param timeStr ÊäÈëµÄ×Ö·û´®  | 
| # @return ·µ»ØÖµ. Ê±¼äData¸ñʽ  | 
| # @remarks »ñµÃϵͳʱ¼ä  | 
| def GetDateTimeByStr(timeStr, timeFomat=ChConfig.TYPE_Time_Format):  | 
|     timeStr = timeStr.strip().split(".")[0]  | 
|     try:  | 
|         return datetime.datetime.strptime(timeStr, timeFomat)  | 
|       | 
|     except BaseException , e:  | 
|         ErrLog("%s : %s"%(e , timeStr))  | 
|         return  | 
|       | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄСʱÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄСʱÊý  | 
| def GetPastHour(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastHour Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     return pastTimeDelta.days * 24 + pastTimeDelta.seconds / 3600  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄ·ÖÖÓÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄ·ÖÖÓÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄ·ÖÖÓÊý  | 
| def GetPastMinute(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastMinute Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     #ÌìÊý * 24Сʱ * 60 ·ÖÖÓ + Ãë / 60  | 
|     return pastTimeDelta.days * 24 * 60 + pastTimeDelta.seconds / 60  | 
|   | 
| ##»ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý  | 
| # @param dateTimeStr ±È½Ïʱ¼ä×Ö·û Èç"2010-05-26 11:21:25"  | 
| # @return ·µ»ØÖµ, Ïà²îµÄÃëÊý  | 
| # @remarks »ñµÃÓëÏÖʵʱ¼ä²î¾àµÄÃëÊý  | 
| def GetPastSeconds(dateTimeStr):  | 
|     pastTimeDelta = __GetPastTimeDelta(dateTimeStr)  | 
|       | 
|     if pastTimeDelta == None:  | 
|         ErrLog("GetPastMinute Err dateTimeStr = %s"%(dateTimeStr))  | 
|         return 0  | 
|   | 
|     return pastTimeDelta.days*24*60*60 + pastTimeDelta.seconds  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý  | 
| # @param compareTimeStr ±È½ÏµÄʱ¼ä×Ö·û, Èç"2010-05-26 11:21:25"  | 
| # @return class timedelta ÊµÀý »ò None  | 
| # @remarks »ñÈ¡2¸öʱ¼äÖ®¼ä²îÒìµÄTimeDeltaÀàʵÀý  | 
| def __GetPastTimeDelta(compareTimeStr):  | 
|     #ÏÖÔÚʱ¼ä  | 
|     curDataTime = GetCurrentTime()  | 
|     #±È½Ïʱ¼ä  | 
|     compareDataTime = GetDateTimeByStr(compareTimeStr)  | 
|     #»ñȡת»»ºóµÄʱ¼äÒì³£  | 
|     if curDataTime == None or compareDataTime == None:  | 
|         return  | 
|       | 
|     return (curDataTime - compareDataTime)  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ2¸öʱ¼äÏà²îµÄ·ÖÖÓÊý  | 
| # @param curTime ÏÖÔÚʱ¼ä  | 
| # @param tagTime ±È½Ïʱ¼ä  | 
| # @return ·µ»ØÖµ, Ïà²îµÄ·ÖÊý  | 
| # @remarks »ñµÃ2¸öʱ¼äÏà²îµÄ·ÖÖÓÊý  | 
| def GetDiff_Minute(curTime , tagTime):  | 
|     diff_Time = curTime - tagTime  | 
|     #ÌìÊý * 24Сʱ * 60 ·ÖÖÓ + Ãë / 60  | 
|     return diff_Time.days * 24 * 60 + diff_Time.seconds / 60  | 
|   | 
| def GetDiff_Day(timeA , timeB):  | 
|     ## »ñÈ¡ timeA - timeB Ïà²îµÄÈÕÆÚÌìÊý  | 
|     dateTimeA = ChangeTimeNumToDatetime(timeA)  | 
|     dateTimeA = datetime.datetime(dateTimeA.year, dateTimeA.month, dateTimeA.day, 0, 0, 0)  | 
|     dateTimeB = ChangeTimeNumToDatetime(timeB)  | 
|     dateTimeB = datetime.datetime(dateTimeB.year, dateTimeB.month, dateTimeB.day, 0, 0, 0)  | 
|     return (dateTimeA - dateTimeB).days  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡Ó뵱ǰʱ¼äÏà²îÌìÊýµÄdatetime¸ñʽÊý¾Ý  | 
| # @param diffDays ²î¾àÌìÊý  | 
| # @return datetime ÀàÐÍÊý¾Ý  | 
| # @remarks ¿Í»§¶Ë·â°üÏìÓ¦  | 
| def GetDatetimeByDiffDays(diffDays):  | 
|     return GetCurrentTime() + datetime.timedelta(days = diffDays)  | 
| #---------------------------------------------------------------------  | 
| ##¸ù¾ÝNPCµÄÀàÐÍÑ¡Ôñ·µ»Ø¶ÔÏó  | 
| # @param npcID NPCID  | 
| # @return ·µ»ØÖµ, ¶ÔÏóÀàÐÍ  | 
| # @remarks ¸ù¾ÝNPCµÄÀàÐÍÑ¡Ôñ·µ»Ø¶ÔÏó  | 
| def FindNPCByID(npcID):  | 
|     curTag = GetNPCManager().FindNPCByID(npcID)  | 
|     return __GetSummonTagNPC(curTag)  | 
|   | 
| def FindNPCByNPCID(npcID):  | 
|     npcMgr = GetNPCManager()  | 
|     findNPC = npcMgr.FindGameNPCByNPCID(npcID)  | 
|     if not findNPC:  | 
|         findNPC = FindSummerNPCByNPCID(npcID)  | 
|     if findNPC:  | 
|         return findNPC  | 
|     return  | 
|   | 
| def FindSummerNPCByNPCID(npcID):  | 
|     npcMgr = GetNPCManager()  | 
|     for index in xrange(npcMgr.GetSummonNPCCount()):  | 
|         curNPC = npcMgr.GetSummonNPCAt(index)  | 
|         if curNPC.GetID() == 0:  | 
|             continue  | 
|         if curNPC.GetNPCID() == npcID:  | 
|             return curNPC  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¸ù¾ÝNPCµÄÀàÐÍÑ¡Ôñ·µ»Ø¶ÔÏó  | 
| # @param npcIndex NPCË÷Òý  | 
| # @return ·µ»ØÖµ, ¶ÔÏóÀàÐÍ  | 
| # @remarks ¸ù¾ÝNPCµÄÀàÐÍÑ¡Ôñ·µ»Ø¶ÔÏó  | 
| def GetNPCByIndex(npcIndex):  | 
|     curTag = GetNPCManager().GetNPCByIndex(npcIndex)  | 
|     return __GetSummonTagNPC(curTag)  | 
|   | 
| ##################################################  | 
| #ÓÎÏ·±äÁ¿³õʼ»¯  | 
| __GameWorld = IPY_GameWorld.IPY_GameWorld()  | 
| GameData = IPY_GameWorld.GetGameData()  | 
| ItemFactory = IPY_GameWorld.IPY_ItemFactory()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡GameWorldʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, GameWorldʵÀý  | 
| # @remarks »ñÈ¡GameWorldʵÀý  | 
| def GetGameWorld():  | 
|     return __GameWorld  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡NPCManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, NPCManagerʵÀý  | 
| # @remarks »ñÈ¡NPCManagerʵÀý  | 
| def GetNPCManager():  | 
|     return __GameWorld.GetNPCManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡TeamManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, TeamManagerʵÀý  | 
| # @remarks »ñÈ¡TeamManagerʵÀý  | 
| def GetTeamManager():  | 
|     return __GameWorld.GetTeamManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡PlayerManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, PlayerManagerʵÀý  | 
| # @remarks »ñÈ¡PlayerManagerʵÀý  | 
| def GetPlayerManager():  | 
|     return __GameWorld.GetPlayerManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡MapItemManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, MapItemManagerʵÀý  | 
| # @remarks »ñÈ¡MapItemManagerʵÀý  | 
| def GetMapItemManager():  | 
|     return __GameWorld.GetMapItemManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡MapCopyPlayerManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, MapCopyPlayerManagerʵÀý  | 
| # @remarks »ñÈ¡MapCopyPlayerManagerʵÀý  | 
| def GetMapCopyPlayerManager():  | 
|     return __GameWorld.GetMapCopyPlayerManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡MapʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, MapʵÀý  | 
| # @remarks »ñÈ¡MapʵÀý  | 
| def GetMap():  | 
|     return __GameWorld.GetMap()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡MailʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, MailʵÀý  | 
| # @remarks »ñÈ¡MailʵÀý  | 
| def GetMail():  | 
|     return __GameWorld.GetMail()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡ScriptʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, ScriptʵÀý  | 
| # @remarks »ñÈ¡ScriptʵÀý  | 
| def GetScript():  | 
|     return __GameWorld.GetScript()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡GameFBʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, GameFBʵÀý  | 
| # @remarks »ñÈ¡GameFBʵÀý  | 
| def GetGameFB():  | 
|     return __GameWorld.GetGameFB()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡AllFbNPCManagerʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, AllFbNPCManagerʵÀý  | 
| # @remarks »ñÈ¡AllFbNPCManagerʵÀý  | 
| def GetAllFbNPCManager():  | 
|     return __GameWorld.GetAllFbNPCManager()  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡SummonNPCʵÀý  | 
| # @param curTagNPC NPCʵÀý  | 
| # @return ·µ»ØÖµ, SummonNPCʵÀý  | 
| # @remarks »ñÈ¡SummonNPCʵÀý  | 
| def __GetSummonTagNPC(curTagNPC):  | 
|     if curTagNPC == None:  | 
|         return None  | 
|     npcObj = curTagNPC.GetGameNPCObjType()  | 
|     if npcObj == IPY_GameWorld.gnotSummon:  | 
|         return GetNPCManager().FindSummonNPCByID(curTagNPC.GetID())  | 
|       | 
|     elif npcObj == IPY_GameWorld.gnotTruck:  | 
|         return GetNPCManager().FindTruckByID(curTagNPC.GetID())  | 
|       | 
|     elif npcObj == IPY_GameWorld.gnotPet:  | 
|         return GetNPCManager().FindPetByID(curTagNPC.GetID())  | 
|       | 
|     return curTagNPC  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃ¸ÃNPCÊÇ·ñÊÇÎÞÏÞ·ÀÓùÀàÐÍ  | 
| # @param curObj ¶ÔÏóObj  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks »ñµÃ¸ÃNPCÊÇ·ñÊÇÎÞÏÞ·ÀÓùÀàÐÍ  | 
| def GetNPC_Is_Gate(curObj):  | 
|     if curObj.GetGameObjType() == IPY_GameWorld.gotNPC and curObj.GetType() in [IPY_GameWorld.ntWall , IPY_GameWorld.ntDeer , IPY_GameWorld.ntDefenceMax]:  | 
|         return True  | 
|       | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¸ù¾ÝobjµÃµ½¾ßÌåµÄÀà (¸ù¾ÝË÷Òý,ÔÚËùÓеĵØÍ¼¸±±¾(Ïß·ÖÐ),²éÕÒ)  | 
| # @param obj ¶ÔÏó  | 
| # @return ·µ»ØÖµ, ÊµÀý  | 
| # @remarks ¸ù¾ÝobjµÃµ½¾ßÌåµÄÀà (¸ù¾ÝË÷Òý,ÔÚËùÓеĵØÍ¼¸±±¾(Ïß·ÖÐ),²éÕÒ)  | 
| def GetObjDetail(obj):  | 
|     objType = obj.GetGameObjType()  | 
|     objIndex = obj.GetIndex()  | 
|     if objType == IPY_GameWorld.gotPlayer:  | 
|         return GetPlayerManager().GetPlayerByIndex(objIndex)  | 
|       | 
|     elif objType == IPY_GameWorld.gotNPC:  | 
|         return GetNPCByIndex(objIndex)  | 
|       | 
|     elif objType == IPY_GameWorld.gotItem:  | 
|         return GetMapItemManager().GetPoolItemByIndex(objIndex)  | 
|       | 
|     ErrLog("»ñµÃobjÀàʧ°Ü objType = %s , objIndex = %s"%(objType , objIndex))  | 
|     return None  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##¸ù¾ÝobjID»ñµÃ¾ßÌåµÄÀà(ÔÚµØÍ¼µ±Ç°¸±±¾(Ïß·ÖвéÕÒ))  | 
| # @param objID ¶ÔÏóID  | 
| # @param objType ¶ÔÏóÀàÐÍ  | 
| # @return ·µ»ØÖµ, ÊµÀý  | 
| # @remarks ¸ù¾ÝobjID»ñµÃ¾ßÌåµÄÀà(ÔÚµØÍ¼µ±Ç°¸±±¾(Ïß·ÖвéÕÒ))  | 
| def GetObj(objID, objType):  | 
|     if objType == IPY_GameWorld.gotPlayer:  | 
|         return GetMapCopyPlayerManager().FindPlayerByID(objID)  | 
|       | 
|     elif objType == IPY_GameWorld.gotNPC:  | 
|         return FindNPCByID(objID)  | 
|       | 
|     elif objType == IPY_GameWorld.gotItem:  | 
|         return GetMapItemManager().GetItemByID(objID)  | 
|       | 
|     return None  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡ItemFactoryʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, ItemFactoryʵÀý  | 
| # @remarks »ñÈ¡ItemFactoryʵÀý  | 
| def GetItemFactory():  | 
|     return ItemFactory  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡GameDataʵÀý  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, GameDataʵÀý  | 
| # @remarks »ñÈ¡GameDataʵÀý  | 
| def GetGameData():  | 
|     return GameData  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÄÚÍøGMµ÷ÊÔÊä³öÐÅÏ¢  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param msg ÏûÏ¢ÁÐ±í  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ÄÚÍøGMµ÷ÊÔÊä³öÐÅÏ¢  | 
| def GodLog(curPlayer, msg):  | 
|     if curPlayer.GetGMLevel() != ChConfig.Def_GM_LV_God:  | 
|         return  | 
|       | 
|     DebugAnswer(curPlayer, msg)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Õý³£Èռǵ÷ÊÔÊä³öÐÅÏ¢  | 
| # @param msg ÏûÏ¢  | 
| # @param playerID Íæ¼ÒID  | 
| # @param par ÏûÏ¢²ÎÊý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Õý³£Èռǵ÷ÊÔÊä³öÐÅÏ¢  | 
| def Log(msg, playerID = 0, par = 0):  | 
|     LogUI.Msg('%s\t%s\t%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Òì³£Èռǵ÷ÊÔÊä³öÐÅÏ¢  | 
| # @param msg ÏûÏ¢  | 
| # @param playerID Íæ¼ÒID  | 
| # @param par ÏûÏ¢²ÎÊý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Òì³£Èռǵ÷ÊÔÊä³öÐÅÏ¢  | 
| def ErrLog(msg, playerID = 0, par = 0):  | 
|     LogUI.Msg('%s\t%s\t###Error:%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| ##DEBUGµ÷ÊÔÊä³öÐÅÏ¢  | 
| # @param msg ÏûÏ¢  | 
| # @param playerID Íæ¼ÒID  | 
| # @param par ÏûÏ¢²ÎÊý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DebugLog(msg, playerID = 0, par = 0):  | 
|     if not GetGameWorld().GetDebugLevel():  | 
|         return  | 
|       | 
|     LogUI.Msg('%s\t%s\tPyDebug:%s'%(par, playerID, msg))  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃµ±Ç°·þÎñÆ÷¿ç·þID  | 
| # @param ÎÞ  | 
| # @return  | 
| def GetMergeServerID():  | 
|     global MergeServerID  | 
|       | 
|     if not MergeServerID:  | 
|         rootPath = ChConfig.GetServerRootPath()  | 
|         mergeServerIniFile = rootPath + "\\ZoneServerGroup\\rungate\\InterfaceServer\\MultiServerWarProxyServer\\Config\\config.ini"  | 
|         if not os.path.isfile(mergeServerIniFile):  | 
|             ErrLog('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))  | 
|             raise Exception('ÎÞ·¨ÕÒµ½Îļþ = %s'%(mergeServerIniFile))  | 
|           | 
|         mergeServerIni = ConfigParser.ConfigParser()  | 
|         mergeServerIni.read(mergeServerIniFile)  | 
|           | 
|         section, option = "Config", "ServerID"  | 
|         if not mergeServerIni.has_option(section, option):  | 
|             ErrLog("%s ÕÒ²»µ½ÅäÖÃ: section=%s,option=%s" % (mergeServerIniFile, section, option))  | 
|             return 0  | 
|           | 
|         MergeServerID = ToIntDef(mergeServerIni.get(section, option))  | 
|         Log("¶ÁÈ¡ MergeServerID=%s" % MergeServerID)  | 
|           | 
|     return MergeServerID  | 
|   | 
| ##»ñµÃµ±Ç°·þÎñÆ÷µÄ°æ±¾ºÅ  | 
| # @param ÎÞ  | 
| # @return ·µ»ØÖµ, ·þÎñÆ÷°æ±¾ºÅ  | 
| # @remarks »ñµÃµ±Ç°·þÎñÆ÷µÄ°æ±¾ºÅ  | 
| def GetServerVersion():  | 
|     return GetGameWorld().GetServerVersion()  | 
|   | 
| def GetServerGroupID():  | 
|     # ·þÎñÆ÷×éID£º ´ú±íһ̨·þÎñÆ÷Öаüº¬µÄºÏ·þ¡¢»ì·þµÄ¸÷Æ½Ì¨Çø·þ×é³ÉµÄÒ»¸ö¶ÀÁ¢ÓÎÏ·Çø·þ·þÎñÆ÷»·¾³, ÓÃij¸öIDÀ´´ú±í´Ë·þÎñÆ÷  | 
|     #            ÔÚ¿ç·þ»·¾³ÖУ¬´ËID¾ÍÊÇ´ú±íÀ´×Ôͬһ̨·þÎñÆ÷×Ó·þµÄÍæ¼Ò  | 
|     # ·þÎñÆ÷×éIDÉú³É¹æÔò: DBƽ̨±êʶ¶ÔÓ¦±àºÅ * 1000000 + DBÅäÖõÄServerID  | 
|     # ServerIDÖ§³Ö·¶Î§: 1~999999  | 
|     # Æ½Ì¨±àºÅÖ§³Ö·¶Î§£º1~2000  | 
|     platform = GetPlatform()  | 
|     serverNum = GetPlatformServerNum(platform)  | 
|     if not serverNum:  | 
|         return 0  | 
|     serverNum = max(1, min(2000, serverNum))  | 
|     serverID = max(1, min(999999, GetServerID()))  | 
|     return serverNum * 1000000 + serverID  | 
|   | 
| def GetPlatformServerNum(platform):  | 
|     # »ñÈ¡·þÎñÆ÷µÄƽ̨±àºÅ  | 
|     platformNumDict = ReadChConfig.GetDBEvalChConfig("DBPlatformNum")  | 
|     #===========================================================================  | 
|     # if platform not in platformNumDict:  | 
|     #    ErrLog("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)  | 
|     #    raise Exception("DBPlatformNumûÓÐÅäÖø÷þÎñÆ÷ƽ̨Ëù¶ÔÓ¦µÄ±àºÅ£¡platfrom=%s" % platform)  | 
|     #===========================================================================  | 
|     return platformNumDict.get(platform, 0)  | 
|   | 
| ##»ñµÃµ±Ç°·þÎñÆ÷ƽ̨  | 
| # @param ÎÞ  | 
| # @return  | 
| def GetPlatform():  | 
|     return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")  | 
|   | 
| ##»ñµÃµ±Ç°·þÎñÆ÷ID  | 
| # @param ÎÞ  | 
| # @return  | 
| def GetServerID():  | 
|     return ToIntDef(GetServerSID()[1:], 0)  | 
|   | 
| def GetServerSID():  | 
|     ##»ñµÃµ±Ç°·þÎñÆ÷ID, ´øsµÄ  | 
|     return ReadChConfig.GetPyMongoConfig("platform", "ServerID")  | 
|   | 
| def GetCreateRoleDays(curPlayer):  | 
|     # »ñÈ¡´´½ÇµÚ¼¸Ìì  | 
|     createRoleTime = curPlayer.GetCreateRoleTime()  | 
|     diffTime = GetCurrentTime() - GetDateTimeByStr(createRoleTime.split(" ")[0], ChConfig.TYPE_Time_Format_Day)  | 
|     return diffTime.days + 1  | 
|   | 
| Def_AccID_Split_Sign = "@"  | 
|   | 
| ##Íæ¼ÒÓÎÏ·Õ˺Ÿñʽ: Æ½Ì¨Õ˺Å@ƽ̨Ãû@sÇø·þID, Æ½Ì¨Õ˺ſÉÄÜ´ø@£¬ÈçÓÊÏäyhlz123@qq.com@173on_lan@s519  | 
| ##»ñÈ¡Íæ¼ÒËùÊôÇø·þID  | 
| # @param curPlayer  | 
| # @return  | 
| def GetPlayerServerID(curPlayer):  | 
|     accID = curPlayer.GetAccID()  | 
|     infoList = accID.split(Def_AccID_Split_Sign)  | 
|     return 0 if len(infoList) < 3 else int(infoList[-1][1:])  | 
|   | 
| def GetPlayerServerSID(curPlayer):  | 
|     # ·µ»Øº¬sµÄserverID  | 
|     accID = curPlayer.GetAccID()  | 
|     infoList = accID.split(Def_AccID_Split_Sign)  | 
|     return "" if len(infoList) < 3 else infoList[-1]  | 
|   | 
| def GetPlayerMainServerID(accIDPlatform):  | 
|     # Íæ¼ÒºÏ·þºóËùÊôÖ÷·þID  | 
|     # @param accIDPlatform: Íæ¼ÒÕ˺ÅËùÊôµÄƽ̨  | 
|     mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)  | 
|     if mainServerID != None:  | 
|         return mainServerID  | 
|     return GetServerID()  | 
|   | 
| ##»ñÈ¡Íæ¼ÒËùÊôƽ̨  | 
| def GetPlayerPlatform(gameAccID):  | 
|     infoList = gameAccID.split(Def_AccID_Split_Sign)  | 
|     return "" if len(infoList) < 3 else infoList[-2]  | 
|   | 
| ##»ñȡƽ̨Õ˺Š | 
| def GetPlatformAccID(gameAccID):  | 
|     infoList = gameAccID.split(Def_AccID_Split_Sign)  | 
|     paInfoList = infoList[:-2]  | 
|     platformAccID = Def_AccID_Split_Sign.join(paInfoList)  | 
|     return platformAccID  | 
|   | 
| def GetSessionID(curPlayer):  | 
|     return md5.md5(curPlayer.GetAccID() + curPlayer.GetAccountData().GetLastLoginTime() +'mobile').hexdigest()  | 
|   | 
| def GetAccountType(curPlayer):  | 
|     return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_Account_Type)  | 
|   | 
| PDict_ChannelCodeNum = "PDict_ChannelCodeNum"  | 
|   | 
| ##ÉèÖÃÍæ¼ÒÕ˺ÅËùÊôƵµÀ  | 
| # @param curPlayer  | 
| # @return  | 
| def SetPlayerChannelCode(curPlayer, channelCode):  | 
|     ChannelCodeDict = ReadChConfig.GetEvalChConfig("ChannelCode")  | 
|       | 
|     if not channelCode:  | 
|         curPlayer.NomalDictDelProperty(PDict_ChannelCodeNum)  | 
|         return  | 
|       | 
|     codeList = ChannelCodeDict.values()  | 
|     if channelCode not in codeList:  | 
|         ErrLog("Can not find channel code(%s) in ChannelCode.txt, please check!"   | 
|                % channelCode, curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     for codeNum, code in ChannelCodeDict.items():  | 
|           | 
|         if code == channelCode:  | 
|             curPlayer.NomalDictAddProperty(PDict_ChannelCodeNum, codeNum)  | 
|             DebugLog("SetPlayerChannelCode code=%s,num=%s" % (channelCode, codeNum), curPlayer.GetPlayerID())  | 
|             break  | 
|           | 
|     return  | 
|   | 
| ##»ñÈ¡Íæ¼ÒÕ˺ÅËùÊôƵµÀ  | 
| # @param curPlayer  | 
| # @return  | 
| def GetPlayerChannelCode(curPlayer):  | 
|     codeNum = curPlayer.NomalDictGetProperty(PDict_ChannelCodeNum)  | 
|     if codeNum <= 0:  | 
|         return ""  | 
|       | 
|     ChannelCodeDict = ReadChConfig.GetEvalChConfig("ChannelCode")  | 
|     return ChannelCodeDict.get(codeNum, "")  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##´ó¶î¶È½ðÇ®¼Ç¼  | 
| # @param tradeGold ÎïÆ·ÊÛ¼Û½ð×Ó  | 
| # @param tradeSilver ÎïÆ·ÊÛ¼ÛÒø×Ó  | 
| # @param tradeItemID ÎïÆ·ID  | 
| # @param tradeItemCount ÎïÆ·ÊýÁ¿  | 
| # @param senderID Íæ¼ÒID  | 
| # @param senderGold Íæ¼ÒÓµÓнð×Ó  | 
| # @param senderSilver Íæ¼ÒÓµÓÐÒø×Ó  | 
| # @param receiverID Ä¿±êÍæ¼ÒID  | 
| # @param receiverGold Ä¿±êÍæ¼ÒÓµÓнð×Ó  | 
| # @param receiverSilver Ä¿±êÍæ¼ÒÓµÓÐÒø×Ó  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ´ó¶î¶È½ðÇ®¼Ç¼  | 
| def NoteDownLargeTrade(tradeGold = 0, tradeSilver = 0, tradeItemID = 0, tradeItemCount = 0,   | 
|                            senderID = 0, senderGold = 0, senderSilver = 0,   | 
|                            receiverID = 0, receiverGold = 0, receiverSilver = 0):  | 
|       | 
|     GetGameWorld().DataServer_HugeTradeRec(  | 
|                                                tradeGold,   | 
|                                                tradeSilver,   | 
|                                                tradeItemID,   | 
|                                                tradeItemCount,   | 
|                                                senderID,   | 
|                                                senderGold,   | 
|                                                senderSilver,   | 
|                                                receiverID,   | 
|                                                receiverGold,   | 
|                                                receiverSilver  | 
|                                                )  | 
| #---------------------------------------------------------------------  | 
| ##¼ÇÂ¼Íæ¼Ò½ðÇ®Êý  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param itemID ÎïÆ·ID  | 
| # @param itemCount ÎïÆ·ÊýÁ¿  | 
| # @param itemName ÎïÆ·Ãû×Ö  | 
| # @param moneyType »õ±ÒÀàÐÍ  | 
| # @param moneyCount »õ±ÒÊýÁ¿  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ¼ÇÂ¼Íæ¼Ò½ðÇ®Êý  | 
| def Login_Interface_GoldRec(curPlayer, typeID, typeCount, typeName, moneyType, moneyCount):  | 
|     #½ð×Ó  | 
|     if moneyType == IPY_GameWorld.TYPE_Price_Gold_Money:  | 
|         curPlayer.Interface_GoldRec(typeID, typeCount, typeName, moneyCount, 0)  | 
|     #½ðƱ  | 
|     elif moneyType == IPY_GameWorld.TYPE_Price_Gold_Paper:  | 
|         curPlayer.Interface_GoldRec(typeID, typeCount, typeName, 0, moneyCount)  | 
|           | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##·þÎñÆ÷¶ËÖØÖÃÍæ¼ÒλÖÃ(½öÓÃÓÚÕý³£Çé¿öÏÂ,²»Æµ·±µ÷ÓÃʱºò,ÖØÖÃÍæ¼Ò×ø±ê)  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param posX ×ø±êX  | 
| # @param posY ×ø±êY  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ·þÎñÆ÷¶ËÖØÖÃÍæ¼ÒλÖÃ(½öÓÃÓÚÕý³£Çé¿öÏÂ,²»Æµ·±µ÷ÓÃʱºò,ÖØÖÃÍæ¼Ò×ø±ê)  | 
| def ResetPlayerPos(curPlayer, posX, posY, reason=0, isResetPet=False):  | 
|     if not GetMap().CanMove(posX, posY):  | 
|         ErrLog('ResetPlayerPos ³¢ÊÔÒÆ¶¯µ½Õϰµã, posX = %s, posY = %s'%(posX, posY), curPlayer.GetID())  | 
|         return  | 
|       | 
|     #·þÎñÆ÷Ö÷¶¯ÖØÖÃÍæ¼ÒλÖ࣬ÐèÒªÏÈÇå¿ÕÍæ¼ÒÒÆ¶¯´íÎó´ÎÊý¾àÀ룬·ñÔòÍæ¼ÒÓпÉÄÜÒòÎªÒÆ¶¯¾àÀë¹ýÔ¶¶øµôÏß  | 
|     curPlayer.ResetPos(posX , posY, reason)  | 
|     ClearPlayerPosCount(curPlayer)  | 
|     #  | 
|     if isResetPet:  | 
|         rolePet = curPlayer.GetPetMgr().GetFightPet()  | 
|         if rolePet:  | 
|             import NPCCommon  | 
|             posX, posY = NPCCommon.NPCControl(rolePet).GetMoveNearPos(curPlayer.GetPosX(), curPlayer.GetPosY(), 1)  | 
|             rolePet.ResetPos(posX, posY)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Çå¿ÕÍæ¼ÒÒÆ¶¯´íÎó´ÎÊý  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Çå¿ÕÍæ¼ÒÒÆ¶¯´íÎó´ÎÊý  | 
| def ClearPlayerPosCount(curPlayer):  | 
|     curPlayer.SetMoveCount(0)  | 
|     curPlayer.SetMoveDistDiff(0)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÑéÖ¤µ±Ç°Ê±¼äÊÇ·ñÔÚÖ¸¶¨Ê±¼ä¶ÎÄÚ  | 
| # @param curTime µ±Ç°Ê±¼ä  | 
| # @param actSect Ö¸¶¨Ê±¼ä¶Î  | 
| # @return ·µ»ØÖµ, ÊÇ·ñͨ¹ý¼ì²é  | 
| # @remarks ÑéÖ¤µ±Ç°Ê±¼äÊÇ·ñÔÚÖ¸¶¨Ê±¼ä¶ÎÄÚ  | 
| def IsAtActTime(curTime, actSect):  | 
|     #ÎÞʱ¼ä¶ÎÏÞÖÆ  | 
|     if not actSect:  | 
|         return True  | 
|       | 
|     #Ôڻʱ¼ä¶Î  | 
|     if GetDateTimeByStr(actSect[0]) <= curTime <= GetDateTimeByStr(actSect[1]):  | 
|         return True  | 
|       | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ##»ñµÃµÈ¼¶²Î¿¼»õ±Ò  | 
| # @param curLV ²éÕҵȼ¶  | 
| # @return µ±Ç°µÈ¼¶²Î¿¼»õ±Ò  | 
| # @remarks »ñµÃµÈ¼¶²Î¿¼»õ±Ò  | 
| def GetReMoney(curLV):  | 
|     return 0  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##ÉèÖÃÍæ¼ÒTickTime  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param funcKey ×Öµä  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ÉèÖÃÍæ¼ÒTickTime  | 
| def SetPlayerTickTime(curPlayer, funcKey, tick):  | 
|     #¼ä¸ôδµ½  | 
|     if tick - curPlayer.GetTickByType(funcKey) < ChConfig.TYPE_Player_Tick_Time[funcKey]:  | 
|         return False  | 
|       | 
|     curPlayer.SetTickByType(funcKey, tick)  | 
|     return True  | 
| #---------------------------------------------------------------------  | 
| ## ´ÓÁбíÖвúÉúÎïÆ·Áбí<²»Öظ´>  | 
| #  @param riseList Ëæ»úÁÐ±í  | 
| #  @param randomNum Ëæ»ú´ÎÊý  | 
| #  @param defValue Ä¬ÈÏ·µ»ØÖµ  | 
| #  @param maxRate ×î´ó¸ÅÂÊ  | 
| #  @return Ëæ»úµ½µÄÐÅÏ¢ÁÐ±í  | 
| def GetResultByRandomListEx(riseList, randomNum, defValue=None, maxRate=None):  | 
|     if randomNum <= 0:  | 
|         return defValue  | 
|       | 
|     dataInfo = [] # Ëæ»ú³éÈ¡ºó ÐÅÏ¢ÁÐ±í  | 
|       | 
|     # Ëæ»ú´ÎÊý ´óÓÚ Ôö³¤ÁÐ±í³¤¶È Î¥·¨  | 
|     listLen = len(riseList)  | 
|     if listLen < randomNum:  | 
|         return defValue  | 
|     # Ëæ»ú´ÎÊý µÈÓÚ Ôö³¤ÁÐ±í³¤¶È ·µ»Ø È«ÁбíÐÅÏ¢  | 
|     elif listLen == randomNum:  | 
|         for data in riseList:  | 
|             dataInfo.append(data[1])  | 
|         return dataInfo[:] if dataInfo else []  | 
|       | 
|     tempRiseList = copy.deepcopy(riseList) # ²Ù×÷ÓàÁÙʱÔö³¤ÁÐ±í  | 
|     maxRate = maxRate if maxRate else tempRiseList[-1][0] # Ä¬ÈÏ×î´ó¸ÅÂÊ  | 
|       | 
|     # ¿ªÊ¼Ëæ»ú  | 
|     for i in range(randomNum):  | 
|         rate = random.randint(0, maxRate)  | 
|         for j, data in enumerate(tempRiseList):  | 
|             if rate > data[0]:  | 
|                 continue  | 
|             dataInfo.append(data[1])  | 
|               | 
|             # ÖØ×éÔö³¤ÁÐ±í  | 
|             tempRiseList = ResetRiseList(tempRiseList, j)  | 
|             # ÖØÖÃ×î´ó¸ÅÂÊ  | 
|             maxRate = tempRiseList[-1][0]  | 
|             break  | 
|           | 
|     return dataInfo[:] if dataInfo else []  | 
|   | 
| ## ÖØÖÃÔö³¤ÁÐ±í  | 
| #  @param riseList Ôö³¤ÁÐ±í  | 
| #  @param delIndex É¾³ýµÄ³ÉÔ±Ë÷Òý<´Ó0¿ªÊ¼>  | 
| #  @return ÐÂÔö³¤ÁÐ±í  | 
| def ResetRiseList(riseList, delIndex):  | 
|     riseListLen = len(riseList)  | 
|     # Ôö³¤ÁбíΪ¿Õ  | 
|     if riseListLen <= 0:  | 
|         return []  | 
|     # É¾³ý³ÉÔ±Ë÷ÒýÔ½½ç  | 
|     if delIndex >= riseListLen:  | 
|         return riseList[:]  | 
|       | 
|     tempRiseList = copy.deepcopy(riseList)  # ²Ù×÷ÓàÁÙʱÔö³¤ÁÐ±í  | 
|     lastBaseRete = tempRiseList[delIndex - 1][0] if delIndex > 0 else 0 # É¾³ýÏÞÉÏÒ»Ïî¸ÅÂÊ  | 
|     baseRate = tempRiseList[delIndex][0]        # É¾³ýÏî¸ÅÂÊ  | 
|     # É¾³ýË÷Òýºó³ÉÔ±,¸ÅÂÊÖØÖà  | 
|     tempList = tempRiseList[(delIndex + 1) : riseListLen]  | 
|     for riseInfo in tempList:  | 
|         riseInfo[0] -= (baseRate - lastBaseRete)  | 
|     return copy.deepcopy(tempRiseList[0:delIndex] + tempList[:])  | 
|   | 
| def GetPlusPieList(srcPieList, plusRate):  | 
|     # »ñÈ¡ÌáÉý¸ÅÂʺóµÄ±ýͼ  | 
|     plusPieList = []  | 
|     for i, rateInfo in enumerate(srcPieList):  | 
|         rate, info = rateInfo  | 
|         srcRate = rate if i == 0 else (rate - srcPieList[i - 1][0]) # Ô¸ÅÂÊ  | 
|         newRate = srcRate if not info else (srcRate + int(srcRate * plusRate / 10000.0)) # ÌáÉýºó¸ÅÂÊ  | 
|         specRate = newRate if not plusPieList else (plusPieList[-1][0] + newRate) # ÌáÉýºó¶ÔÓ¦±ýͼ¸ÅÂÊ  | 
|         plusPieList.append((specRate, info))  | 
|     return plusPieList  | 
|   | 
| ## ´ÓÁбíÖвúÉúÎïÆ·£¬[[¼¸ÂÊ£¬object], ....],Íò·ÖÂÊ  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @return object  | 
| def GetResultByRandomList(randList, defValue=None):  | 
|     if not randList:  | 
|         return defValue  | 
|     rate = random.randint(0, randList[-1][0])  | 
|     return GetResultByRiseList(randList, rate, defValue)  | 
|   | 
| ## Ôö³¤ÁÐ±í£¨ÀàËÆ±ýͼ£©´ÓÖлñµÃÖ¸¶¨µÄÐÅÏ¢  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @param point Ö¸¶¨Öµ  | 
| #  @return µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢ or None  | 
| #  @remarks Áбí½á¹¹£¬Ã¿¸öÔªËØÎªÐ¡ÁÐ±í£¬Ð¡ÁÐ±í³¤¶ÈΪ2£¬µÚÒ»¸öÔªËØÎª±È½ÏÖµ£¬µÚ¶þ¸öΪ¾ßÌåÐÅÏ¢  | 
| def GetResultByRiseList(riseList, point, defValue=None):  | 
|     for smallList in riseList:  | 
|         if point > smallList[0]:  | 
|             continue  | 
|           | 
|         return smallList[1]  | 
|       | 
|     return defValue  | 
|   | 
| ## ´ÓÁбíÖвúÉúÎïÆ·£¬[[È¨ÖØ, object], ....]  | 
| #  @param weightList ´ýÑ¡ÁÐ±í  | 
| def GetResultByWeightList(weightList):  | 
|     randList = []  | 
|     weight = 0  | 
|     for info in weightList:  | 
|         weight += info[0]  | 
|         randList.append([weight, info[1] if len(info) == 2 else info[1:]])  | 
|     if not randList:  | 
|         return  | 
|     rate = random.randint(1, randList[-1][0])  | 
|     return GetResultByRiseList(randList, rate)  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| ## ½«¸ÅÂÊ·Ö²¼Áбíת»»ÎªÔö³¤ÁÐ±í  | 
| #  @param randList ¸ÅÂÊ·Ö²¼ÁÐ±í  | 
| #  @param isCriticalDownward ³éÈ¡µ½ÁÙ½çÖµ¹éÊôÓÚǰһ¸öË÷Òý  | 
| #  @return Ë÷Òý  | 
| def GetIndexByIndependRate(randList, isCriticalDownward = True):  | 
|     # randList°´±ÈÀýת»¯Îª±ýͼ  | 
|     for i in range(len(randList)):  | 
|         if i == 0:  | 
|             continue  | 
|   | 
|         randList[i] += randList[i - 1]  | 
|       | 
|     point = random.randint(0, randList[-1])  | 
|       | 
|     return GetResultByRiseIndex(randList, point, isCriticalDownward)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ´ÓÁбíÖвúÉúÎïÆ·£¬[[¼¸ÂÊ£¬object], ....],Íò·ÖÂÊ  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @return ²úÉúµÄÎïÆ·ÔÚÁбíÖеÄË÷Òý  | 
| def GetResultByRandomIndex(randList):  | 
|     rate = random.randint(0, ChConfig.Def_NPCMapDropRate)  | 
|       | 
|     return GetResultByRiseIndex(randList, rate)  | 
|   | 
|   | 
| ## Ôö³¤ÁÐ±í£¨ÀàËÆ±ýͼ£©´ÓÖлñµÃÖ¸¶¨µÄÐÅÏ¢  | 
| #  @param itemList ´ýÑ¡ÁÐ±í  | 
| #  @param point Ö¸¶¨Öµ  | 
| #  @return ²úÉúµÄÎïÆ·ÔÚÁбíÖеÄË÷Òý  | 
| def GetResultByRiseIndex(riseList, point, isCriticalDownward = True):  | 
|     for index in range(0, len(riseList)):  | 
|         element = riseList[index]  | 
|           | 
|         if isinstance(element, int):  | 
|             cmpPoint = element  | 
|         else:  | 
|             cmpPoint = element[0]  | 
|         if isCriticalDownward:  | 
|             if point > cmpPoint:  | 
|                 continue  | 
|         else:  | 
|             if point >= cmpPoint:  | 
|                 continue  | 
|       | 
|         return index  | 
|       | 
|     return -1  | 
|   | 
| #---------------------------------------------------------------------  | 
|   | 
| ##»ñµÃÓÅ»¯µÄº¯ÊýÖ¸Õë  | 
| # @param func º¯ÊýÖ¸Õë  | 
| # @return ÓÅ»¯ºóµÄº¯ÊýÖ¸Õë  | 
| # @remarks   | 
| def GetPsycoFunc(func):  | 
|     return func  | 
| #    if not __GetPsycoIsOpen():  | 
| #        #¹Ø±Õpsyco, ·µ»ØÔº¯Êý  | 
| #        return func  | 
| #  | 
| #    return psyco.proxy(func)  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##»ñÈ¡psyco¿ª¹Ø  | 
| # @param ÎÞ²ÎÊý  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks   | 
| def __GetPsycoIsOpen():  | 
|     return ReadChConfig.GetEvalChConfig('PsycoSwitch')  | 
|   | 
| ##ÖØÐ¼ÓÔØ½Å±¾.  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ÖØÐ¼ÓÔØ½Å±¾  | 
| def PsycoReload(tick):  | 
|     Log("PsycoReload Begin : time = %s"%GetCurrentDataTimeStr())  | 
|   | 
|     moduleNameList = []  | 
|     for moduleName in sys.modules.keys():  | 
|         moduleNameList.append([moduleName, moduleName.split(".")[-1]])  | 
|   | 
|     TravelFile(ChConfig.ScriptPath, "", moduleNameList)  | 
|     return  | 
|   | 
| ## ±éÀúÎļþ  | 
| #  @param scriptPath  | 
| #  @param filePath  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def TravelFile(scriptPath, filePath, moduleNameList):  | 
|      | 
|     for fileName in os.listdir(scriptPath + filePath):  | 
|           | 
|         if fileName.startswith("."):  | 
|             continue  | 
|           | 
|         curModuleName = fileName.split('.')[0]  | 
|         for reloadName, moduleName in moduleNameList:  | 
|             if curModuleName != moduleName:  | 
|                 continue  | 
|               | 
|             module = sys.modules.get(reloadName)  | 
|               | 
|             if not module:  | 
|                 continue  | 
|               | 
|             reload(module)  | 
|           | 
|         #ÊÇÎļþ¼Ð  | 
|         if os.path.isdir(scriptPath + filePath + "\\" + fileName):  | 
|             TravelFile(scriptPath, filePath + "\\" + fileName + "\\", moduleNameList)  | 
|               | 
|     return  | 
|   | 
|   | 
| ## È«¾Öº¯Êý¼òҪ˵Ã÷£º×ª»¯³Éʱ¡¢·Ö¡¢Ãë  | 
| #  @param ²ÎÊý£ºÊ±¼ä£¨ºÁÃë¼¶£©  | 
| #  @return ·µ»ØÖµ£ºÊ±¡¢·Ö¡¢Ãë  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷£º  | 
| def ChangeInputTime(inputTime):  | 
|     curTimeHour = int(inputTime/1000)/3600  | 
|     curTimeMinute = int(inputTime/1000)/60%60  | 
|     curTimeSecond = int(inputTime/1000)%60  | 
|       | 
|     return curTimeHour,curTimeMinute,curTimeSecond  | 
|   | 
| ## ÈÎÎñÊÇ·ñÒª´¥·¢OSS¼Ç¼  | 
| #  @param missionLV: ÈÎÎñµÈ¼¶  | 
| #  @return  | 
| def IsMissonDR(curPlayer):  | 
|       | 
|     playerLV = curPlayer.GetLV()  | 
|       | 
|     minDRLV = ReadChConfig.GetEvalChConfig('Def_Mission_DR_MinLV')  | 
|       | 
|     if playerLV < minDRLV:  | 
|         return False  | 
|       | 
|     return True  | 
|   | 
|   | 
| ## ¼ì²é×Ö·ûµÄ¹æÔòÊÇ·ñ·ûºÏ  | 
| #  @param inputText ÊäÈëµÄÎÄ×Ö  | 
| #  @return: ÊÇ·ñ·ûºÏ±àÂë¸ñʽ  | 
| def EncodingToUnicode(inputText):  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return False  | 
|       | 
|     if encodingList[0]:  | 
|         #²»z²é  | 
|         return True  | 
|           | 
|     try:  | 
|         unicode(inputText, encodingList[1])  | 
|     except:  | 
|         return False  | 
|       | 
|     return True  | 
|   | 
|   | 
| # »ñµÃÓÎÏ·ÉèÖõÄ×Ö·û±àÂë  | 
| def GetCharacterEncoding():  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return 'utf8'  | 
|     return encodingList[1]  | 
|   | 
|   | 
| # ·þÎñÆ÷ĬÈÏGBK£¬×ªÅäÖñàÂëÈçUTF8£¬Ò»°ãÓÃÓÚÓëÏÔʾ²ã½»»¥£¬²»ÅжÏÊÇ·ñbase64  | 
| def GbkToCode(inputText):  | 
|     encodingList = ReadChConfig.GetEvalChConfig("EncodingTex")  | 
|       | 
|     if len(encodingList) != 2:  | 
|         ErrLog("EncodingTex.txt Error len != 2")  | 
|         return inputText  | 
|       | 
|     try:  | 
|         return inputText.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())  | 
|     except:  | 
|         return inputText  | 
|       | 
|     return inputText  | 
|   | 
| ## ÊÇ·ñ¿ç·þ·þÎñÆ÷  | 
| #  @param None None  | 
| #  @return  | 
| def IsMergeServer():  | 
|     config = MapConfig.GetConfig()  | 
|           | 
|     return config.get('IsMergeWarServe', 0)  | 
|   | 
|   | 
| ## Ê±¼ä¸ñʽת»»³ÉÊýֵʱ¼ä£¬¿É²Î¿¼datetime.datetime.fromtimestamp(102645645)  | 
| #  @param timeNum  | 
| #  @return Ê±¼äÊýÖµ 1970ÄêÆð  | 
| def ChangeTimeStrToNum(timeStr, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     timeStr = datetime.datetime.strptime(timeStr, timeFormat).timetuple()   | 
|     return int(time.mktime(timeStr))  | 
|   | 
| ## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ  | 
| #  @param timeNum: Êýֵʱ¼ä  | 
| #  @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>  | 
| def ChangeTimeNumToStr(timeNum, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     return time.strftime(timeFormat, time.localtime(timeNum))  | 
|   | 
| ## Êýֵʱ¼äת»»³Éʱ¼ä¸ñʽ  | 
| #  @param timeNum: Êýֵʱ¼ä  | 
| #  @return: 2012-03-30 22:16:41 <type 'datetime.datetime'>  | 
| def ChangeTimeNumToDatetime(timeNum, timeFormat=ChConfig.TYPE_Time_Format):  | 
|     timeStr = time.strftime(timeFormat, time.localtime(timeNum))  | 
|     return datetime.datetime.strptime(timeStr, timeFormat)  | 
|   | 
| def CheckTimeIsSameServerDayEx(checkTime):  | 
|     '''ÅжÏÖ¸¶¨timeÖµÓëµ±Ììʱ¼ä¶Ô±ÈÊÇ·ñΪÓÎÏ·ÄÚµÄͬһÌì£»ÌØÊâʱ¼äµã¹ýÌìºó²ÅË㲻ͬÌì  | 
|     ¸Ãº¯ÊýÒ»°ãÓÃÓÚÅжÏij¸ö¹¦ÄܼǼµÄ°æ±¾ÌìÊÇ·ñÓëµ±Ììʱ¼äÊÇͬһÌìµÄÂß¼  | 
|     @return: ÊÇ·ñͬһÌì  | 
|     '''  | 
|     checkDate = ChangeTimeNumToDatetime(checkTime)  | 
|     curDate = GetCurrentTime()  | 
|     if checkDate > curDate:  | 
|         #DebugLog("¼ì²éʱ¼ä±Èµ±Ç°Ê±¼ä´ó")  | 
|         return False  | 
|       | 
|     Def_OnEventHour = ShareDefine.Def_OnEventHour  | 
|     chkYear, chkMonth, chkDay, chkHour = checkDate.year, checkDate.month, checkDate.day, checkDate.hour  | 
|     curYear, curMonth, curDay, curHour = curDate.year, curDate.month, curDate.day, curDate.hour  | 
|       | 
|     # Í¬Ò»ÈÕÆÚµÄ  | 
|     if chkYear == curYear and chkMonth == curMonth and chkDay == curDay:  | 
|         if chkHour < Def_OnEventHour <= curHour:  | 
|             #DebugLog("ͬÈÕÆÚ£¬µ«²»Í¬Ì죡chkHour(%s) < %s <= curHour(%s)" % (chkHour, Def_OnEventHour, curHour))  | 
|             return False  | 
|         #DebugLog("ͬÈÕÆÚ£¬Í¬´óÓÚ»òͬСÓÚ%s, Í¬Ì죡chkHour(%s), curHour(%s)" % (Def_OnEventHour, chkHour, curHour))  | 
|         return True  | 
|       | 
|     checkDateEx = datetime.datetime(chkYear, chkMonth, chkDay, 0, 0, 0)  | 
|     curDateEx = datetime.datetime(curYear, curMonth, curDay, 0, 0, 0)  | 
|     diffDays = (curDateEx - checkDateEx).days  | 
|     if diffDays == 1:  | 
|         if chkHour < Def_OnEventHour:  | 
|             #DebugLog("ÈÕÆÚÏà²îÌìÊý1, ²»Í¬Ìì! chkHour(%s) < %s" % (chkHour, Def_OnEventHour))  | 
|             return False  | 
|           | 
|         if curHour >= Def_OnEventHour:  | 
|             #DebugLog("ÈÕÆÚÏà²îÌìÊý1, ²»Í¬Ìì! curHour(%s) >= %s" % (curHour, Def_OnEventHour))  | 
|             return False  | 
|           | 
|         #DebugLog("ÈÕÆÚÏà²îÌìÊý1, Í¬Ìì! curHour(%s) < %s <= chkHour(%s)" % (curHour, Def_OnEventHour, chkHour))  | 
|         return True  | 
|       | 
|     #DebugLog("ÈÕÆÚÏà²îÌìÊý´óÓÚ1£¬²»Í¬Ò»Ì죡")  | 
|     return False  | 
|   | 
| ## »ñÈ¡Íæ¼ÒµÄÇø·þÃû£¬½öÔÚ¿ç·þÓÐЧ  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @return: Çø·þÃû  | 
| def GetAreaName(curPlayer):  | 
|     operator = curPlayer.GetAccountData().GetOperator()  | 
|     areaID = curPlayer.GetAccountData().GetAreaID()  | 
|       | 
|     # "%s-%s"%(operator, areaID)  | 
|     areaNameInfo = ReadChConfig.GetEvalChConfig("AreaNameInfo")  | 
|     areaName = eval(areaNameInfo.get("NameExpr", ""))  | 
|       | 
|     return areaName  | 
|       | 
|   | 
| ## »ñÈ¡Íæ¼ÒµÄÇø·þÃûCRC£¬½öÔÚ¿ç·þÓÐЧ  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @return: Çø·þÃû  | 
| def GetAreaCrc(curPlayer):  | 
|     areaName = GetAreaName(curPlayer)  | 
|     return CommFunc.GetStrCrc(areaName)  | 
|   | 
|   | 
| ##½«×Öµä2ÖеÄÖµ¼ÓÈë×Öµä1ÖÐ  | 
| # @param dict1 ×Öµä1  | 
| # @param dict2 ×Öµä2  | 
| # @return None   | 
| def AddDictValue(dict1, dict2):  | 
|     for key, value in dict2.items():  | 
|         dict1[key] = dict1.get(key, 0) + value  | 
|           | 
|     return  | 
|   | 
|   | 
| ##½«×Öµä2ÖеÄÖµ¼ÓÈë×Öµä1ÖÐ, Ë¥¼õËã·¨  | 
| # @param dict1 ×Öµä1  | 
| # @param dict2 ×Öµä2  | 
| # @return None   | 
| def CalcAttrDictPer(dict1, dict2):  | 
|     for key, value in dict2.items():  | 
|         value1 = dict1.get(key, 0)  | 
|   | 
|         dict1[key] = value1 + value - value1*value/ShareDefine.Def_MaxRateValue  | 
|           | 
|     return  | 
|   | 
|   | 
| ## »ñµÃ¶ÔÓ¦ÊýλµÄÖµ  | 
| #  @param numValue ÊýÖµ  | 
| #  @param dataIndex ÊýλË÷Òý  | 
| #  @return »ñµÃµÄÖµ   | 
| def GetDataByDigitPlace(numValue, dataIndex):  | 
|     return (numValue/pow(10, dataIndex))%10  | 
|       | 
|   | 
| ## ÉèÖöÔÓ¦ÊýλµÄÖµ  | 
| #  @param numValue ÊýÖµ  | 
| #  @param dataIndex ÊýλË÷Òý  | 
| #  @param dataValue µ±Ç°ÐÞ¸ÄÊýÖµ  | 
| #  @return »ñµÃµÄÖµ   | 
| def ChangeDataByDigitPlace(numValue, dataIndex, dataValue):  | 
|       | 
|     if dataValue < 0 or dataValue > 9 or dataIndex > ShareDefine.Def_PDictDigitCnt:  | 
|         return numValue  | 
|       | 
|     # »ñµÃ¶ÔÓ¦ÊýλµÄÖµ  | 
|     lastTagLV = GetDataByDigitPlace(numValue, dataIndex)  | 
|       | 
|     numValue += pow(10, dataIndex)*(dataValue - lastTagLV)  | 
|     return numValue  | 
|   | 
|   | 
| ## ×Ôдroundº¯Êý  | 
| #  @param num  | 
| #  @return ¼ò»¯ºóÊý  | 
| def MyRound(num):  | 
|     #return int(num + 0.5)  | 
|     #Èç¹û´æÔÚ¸ºÊýÎÊÌ⣬ÓÃÒÔÏ´úÂë  | 
|     return int(num) if abs(num) < abs(int(num)) + 0.5 else int(num) + int(num/abs(num))  | 
|   | 
|   | 
| ## ¸ù¾Ý×Öµäkey»ñÈ¡valueÖµ  | 
| #  @return   | 
| def GetDictValueByKey(attrDict, findKey):  | 
|       | 
|     if findKey in attrDict:  | 
|         return attrDict[findKey]  | 
|       | 
|     for key, value in attrDict.items():  | 
|           | 
|         if isinstance(key, tuple) and findKey in key:  | 
|             return value  | 
|       | 
|     return  | 
|   | 
| ## ¸ù¾Ý×Öµäkey·¶Î§»ñÈ¡valueÖµ  | 
| def GetDictValueByRangeKey(srcDict, findKey, defValue=None):  | 
|       | 
|     if findKey in srcDict:  | 
|         return srcDict[findKey]  | 
|       | 
|     for rangeKey, value in srcDict.items():  | 
|         if isinstance(rangeKey, tuple) and len(rangeKey) == 2 and rangeKey[0] <= findKey <= rangeKey[1]:  | 
|             return value  | 
|     return defValue  | 
|   | 
|   | 
| ## ¸ù¾ÝÍæ¼Ò×Öµä¶ÔÓ¦µÄλֵ, Ê¹Óöà¸ökeyÖ§³ÖNλË÷Òý  | 
| #  @param curPlayer  | 
| #  @param keyFormat ¶¨Òåkey¸ñʽ£¬×¢´Ëkey·Çʵ¼Êkey  | 
| #  @param bit ÐèÒª»ñÈ¡µÄʵ¼Êλֵ  | 
| #  @param isBin ÊÇ·ñ¶þ½øÖƸñʽ´æ´¢Ä£Ê½, Ä¬ÈÏÊÇ  | 
| #  @param keyParam ×Ô¶¨Òåkey¸ñʽµÄÀ©Õ¹²ÎÊý, key±àºÅ²ÎÊýĬÈÏ×îºóÒ»¸ö  | 
| #  @return  | 
| def GetDictValueByBit(curPlayer, keyFormat, bit, isBin=True, keyParam=[]):  | 
|     # ¶þ½øÖÆÄ£Ê½Ò»¸ö¿ÉÒÔ×î¶à¿É´æ´¢31λ£¬Ê®½øÖÆÄ£Ê½×î¶à¿É´æ´¢9λ  | 
|     perKeyMaxBit = 31 if isBin else 9  | 
|     keyNum = bit / perKeyMaxBit  | 
|     keyName = keyFormat % keyNum if not keyParam else keyFormat % tuple(keyParam + [keyNum])  | 
|     dictValue = curPlayer.NomalDictGetProperty(keyName)  | 
|     bitIndex = bit % perKeyMaxBit  | 
|     if isBin:  | 
|         bitValue = dictValue & pow(2, bitIndex)  | 
|         bitValue = 1 if bitValue else 0  | 
|     else:  | 
|         bitValue = GetDataByDigitPlace(dictValue, bitIndex)  | 
|     #DebugLog("GetDictValueByBit keyFormat=%s,isBin=%s,bit=%s,keyNum=%s,keyName=%s,dictValue=%s,bitIndex=%s,bitValue=%s"   | 
|     #         % (keyFormat, isBin, bit, keyNum, keyName, dictValue, bitIndex, bitValue))  | 
|     return bitValue  | 
|   | 
| ## ¸ù¾ÝÍæ¼Ò×Öµä¸üжÔÓ¦µÄλֵ, Ê¹Óöà¸ökeyÖ§³ÖNλË÷Òý  | 
| #  @param curPlayer  | 
| #  @param keyFormat ¶¨Òåkey¸ñʽ£¬×¢´Ëkey·Çʵ¼Êkey  | 
| #  @param bit ÐèÒª¸üеÄʵ¼Êλֵ  | 
| #  @param value ¸üÐÂÖµ  | 
| #  @param isBin ÊÇ·ñ¶þ½øÖƸñʽ´æ´¢Ä£Ê½, Ä¬ÈÏÊÇ  | 
| #  @param keyParam ×Ô¶¨Òåkey¸ñʽµÄÀ©Õ¹²ÎÊý, key±àºÅ²ÎÊýĬÈÏ×îºóÒ»¸ö  | 
| #  @return [ÔÖµ, ÉèÖúóµÄÖµ]  | 
| def SetDictValueByBit(curPlayer, keyFormat, bit, value, isBin=True, keyParam=[]):  | 
|     # ¶þ½øÖÆÄ£Ê½Ò»¸ö¿ÉÒÔ×î¶à¿É´æ´¢31λ£¬Ê®½øÖÆÄ£Ê½×î¶à¿É´æ´¢9λ  | 
|     perKeyMaxBit = 31 if isBin else 9  | 
|     keyNum = bit / perKeyMaxBit  | 
|     keyName = keyFormat % keyNum if not keyParam else keyFormat % tuple(keyParam + [keyNum])  | 
|     dictValue = curPlayer.NomalDictGetProperty(keyName)  | 
|     bitIndex = bit % perKeyMaxBit  | 
|     if isBin:  | 
|         if value:  | 
|             updDictValue = dictValue|pow(2, bitIndex)  | 
|         else:  | 
|             updDictValue = dictValue&(pow(2, perKeyMaxBit + 1) - 1 - pow(2, bitIndex))  | 
|     else:  | 
|         updDictValue = ChangeDataByDigitPlace(dictValue, bitIndex, value)  | 
|     if updDictValue == 0:  | 
|         curPlayer.NomalDictDelProperty(keyName, 0)  | 
|     else:  | 
|         curPlayer.NomalDictAddProperty(keyName, updDictValue)  | 
|     #DebugLog("SetDictValueByBit keyFormat=%s,isBin=%s,bit=%s,keyNum=%s,keyName=%s,dictValue=%s,bitIndex=%s,updDictValue=%s"   | 
|     #         % (keyFormat, isBin, bit, keyNum, keyName, dictValue, bitIndex, updDictValue))  | 
|     return dictValue, updDictValue  | 
|   | 
| ## ÖØÖÃËùÓÐλֵ  | 
| def ResetDictAllBitValue(curPlayer, keyFormat, maxLen, isBin=True, keyParam=[]):  | 
|     perKeyMaxBit = 31 if isBin else 9  | 
|     keyCnt = int(math.ceil(maxLen / float(perKeyMaxBit)))  | 
|     for i in range(keyCnt):  | 
|         keyName = keyFormat % i if not keyParam else keyFormat % tuple(keyParam + [i])  | 
|         curPlayer.NomalDictDelProperty(keyName)  | 
|     return  | 
|   | 
| ## ¹ã²¥ÐÅÏ¢µ½×Ó·þÎñÆ÷ÉÏ  | 
| #  @param operType ¹ã²¥ÀàÐÍ  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param dataInfo ¹ã²¥ÐÅÏ¢  | 
| #  @param isRepeat ÊÇ·ñÖØ¸´  | 
| #  @return None  | 
| def SendBroadcastMerge(operType, mapID, dataInfo, isRepeat=True):  | 
|     msgList = [operType, mapID, dataInfo, isRepeat]  | 
|     msgList = str(msgList)  | 
|     GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'SendBroadcastMergeClient', msgList, len(msgList))  | 
|     return  | 
|   | 
| ## ×Ó·þÎñÆ÷·¢ËÍÐÅÏ¢µ½¿ç·þÖÐÐÄ·þÎñÆ÷  | 
| #  @param operType ÀàÐÍ  | 
| #  @param dataMsg   | 
| #  @return None  | 
| def SendMergerChildToCenterStringData(operType, dataMsg, srcPlayerID=0, queryType=0, queryID=0):  | 
|     msgList = [operType, dataMsg]  | 
|     msgList = str(msgList)  | 
|     GetPlayerManager().GameServer_QueryPlayerResult(srcPlayerID, queryType, queryID,   | 
|                                                     'SendMergerChildMsg', msgList, len(msgList))  | 
|     return  | 
|   | 
| ## ¸ù¾ÝÅÅÐлñÈ¡Ãû´Î¶ÔÓ¦Öµ  | 
| #  @param orderDict {Ãû´Î:obj, ...} Ãû´ÎÖ§³Ö¶ÎÌøÔ¾  | 
| #  @param order Ãû´Î£¬´Ó1¿ªÊ¼  | 
| #  @param isDefaultLast ÕÒ²»µ½µÄÃû´ÎÊÇ·ñĬÈÏÈ¡×îºóÒ»ÃûµÄ  | 
| #  @return obj or None  | 
| def GetOrderValueByDict(orderDict, order, isDefaultLast=True):  | 
|     if order in orderDict:  | 
|         return orderDict[order]  | 
|       | 
|     orderList = sorted(orderDict.keys())  | 
|     if order > 0:  | 
|         for dOrder in orderList:  | 
|             if order <= dOrder:  | 
|                 return orderDict[dOrder]  | 
|           | 
|     # ÕÒ²»µ½µÄĬÈÏÈ¡×îºóÒ»Ãû  | 
|     return orderDict[orderList[-1]] if isDefaultLast else None  | 
|   | 
| ## ¼ì²éÍæ¼ÒtickÀàÐÍCD  | 
| def CheckPlayerTick(curPlayer, tickType, tick):  | 
|     if tick - curPlayer.GetTickByType(tickType) < ChConfig.TYPE_Player_Tick_Time[tickType]:  | 
|         return False  | 
|       | 
|     curPlayer.SetTickByType(tickType, tick)  | 
|     return True  | 
|   | 
|   | 
| ## ¿Í»§¶ËÏÔʾµÈ¼¶  | 
| #  @return: ×ªÉú´ÎÊý, µÈ¼¶  | 
| def GetClientLV(curPlayer):  | 
|     serverLV = curPlayer.GetLV()  | 
|   | 
|     clientLVRule = ReadChConfig.GetEvalChConfig("ClientLVRule")  | 
|     TransRealLVList = clientLVRule[0]  | 
|     TransNewLvList = clientLVRule[1]  | 
|     SplitLVExpDict = clientLVRule[2]  | 
|       | 
|     transCnt = 0 # ×ªÊý  | 
|     for i, reallv in enumerate(TransRealLVList):  | 
|         if serverLV < reallv:  | 
|             transCnt = i  | 
|             break  | 
|         transCnt = i + 1  | 
|   | 
|     curTransRealLV = TransRealLVList[transCnt - 1] # µ±Ç°×ªÊýÆðÊ¼ÕæÊµµÈ¼¶  | 
|     curNewLV = TransNewLvList[transCnt - 1] # µ±Ç°×ªÊýÆðʼÏÔʾµÈ¼¶  | 
|     nextTransRealLV = 99999 if transCnt >= len(TransRealLVList) else TransRealLVList[transCnt] # ÏÂһתÊýÆðÊ¼ÕæÊµµÈ¼¶  | 
|       | 
|     curTransAddSplitLV = 0 # µ±Ç°×ªÊýÒѾÉý¼¶µÄ²ð·Ö¶îÍâµÈ¼¶Êý  | 
|     curTransTotalSplitLV = 0 # µ±Ç°×ªÊýµÄËùÓвð·Ö¾Ñé¶îÍâ×ܵȼ¶Êý  | 
|     for splitRealLV, splitLVList in SplitLVExpDict.items():  | 
|         # ²»Êǵ±Ç°×ªÊýµÄµÈ¼¶²»´¦Àí  | 
|         if splitRealLV < curTransRealLV or splitRealLV >= nextTransRealLV:  | 
|             continue  | 
|         splitLVExCnt = len(splitLVList)  | 
|         curTransTotalSplitLV += splitLVExCnt  | 
|         if splitRealLV < serverLV:  | 
|             curTransAddSplitLV += splitLVExCnt  | 
|               | 
|     # ÊÇ·ñÏÔʾ¾Ñé²ð·ÖµÈ¼¶, ½öÊÊÓÃÓÚ×ÔÉíµÄµ±Ç°µÈ¼¶  | 
|     if serverLV in SplitLVExpDict:  | 
|         curTransAddSplitLV += curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SplitExpLVCnt % serverLV)  | 
|           | 
|     showLV = serverLV if transCnt <= 0 else serverLV - curTransRealLV + curNewLV - curTransTotalSplitLV + curTransAddSplitLV  | 
|     return transCnt, showLV  | 
|   | 
| def AddUniversalGameRec(playerID, recType, valueList, strValueList, notifyType=0, isSort=1):  | 
|     '''  | 
|     @todo: Ìí¼ÓGameServer´æ´¢Í¨ÓüǼ  | 
|     @param recType: Í¨ÓüǼÀàÐÍ, ¶ÔÓ¦ ShareDefine.Def_UniversalGameRecTypeList  | 
|     @param valueList: ÊýÖµÁбí[value1, value2, ...], °´Ë³Ðò, Ö§³Övalue1 ~ value5  | 
|     @param strValueList: ×Ö·ûÖµÁбí[strValue1, strValue2, ...], °´Ë³Ðò, Ö§³ÖstrValue1 ~ strValue3  | 
|     @param notifyType: 0-²»Í¨Öª; 1-֪ͨ±¾ÈË; 2-֪ͨȫ·þ  | 
|     @param isSort: ´æ´¢¼Ç¼ÂúÐèɾ³ýʱÊÇ·ñÐèÒªÏȰ´Ê±¼äÅÅÐò, Ä¬ÈÏ1ÊÇ, ÏȽøÏȳö  | 
|     '''  | 
|     msgStr = str([recType, valueList, strValueList, notifyType, isSort])  | 
|     GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "AddUniversalGameRec", msgStr, len(msgStr))  | 
|     return  | 
|   | 
| def DelUniversalGameRec(recType, playerID=0, notifyType=0):  | 
|     '''  | 
|     @todo: É¾³ýGameServer´æ´¢Í¨ÓüǼ  | 
|     @param recType: Í¨ÓüǼÀàÐÍ, ¶ÔÓ¦ ShareDefine.Def_UniversalGameRecTypeList  | 
|     @param notifyType: 0-²»Í¨Öª; 1-֪ͨ±¾ÈË; 2-֪ͨȫ·þ  | 
|     '''  | 
|     msgStr = str([recType, notifyType])  | 
|     GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "DelUniversalGameRec", msgStr, len(msgStr))  | 
|     return  | 
|   | 
|   | 
| def DebugAnswer(curPlayer, text):  | 
|     '''תÂëºóÔÙ·¢DebugAnswer'''  | 
|     #===========================================================================  | 
|     # if not GetGameWorld().GetDebugLevel():  | 
|     #    return  | 
|     #===========================================================================  | 
|       | 
|     DebugLog(text)  | 
|     text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())  | 
|     curPlayer.DebugAnswer(text)  | 
|     return  | 
|   | 
|   |