| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package Event.EventSrc.Operate_EquipWash  | 
| #  | 
| # @todo:×°±¸Ï´Á·  | 
| # @author hxp  | 
| # @date 2017-08-09  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ×°±¸Ï´Á·  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2017-08-09 15:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import IpyGameDataPY  | 
| import NetPackCommon  | 
| import ChPyNetSendPack  | 
| import PlayerControl  | 
| import PlayerSuccess  | 
| import IPY_GameWorld  | 
| import PlayerActGarbageSorting  | 
| import DataRecordPack  | 
| import PlayerActLogin  | 
| import ShareDefine  | 
| import ItemCommon  | 
| import ChConfig  | 
| import ChEquip  | 
|   | 
| import random  | 
|   | 
|   | 
| Def_EquipWashMaxType = 2 # ×°±¸Ï´Á·×î´ó¹é×éÀàÐÍ  | 
| Def_EquipWashMaxAttrCount = 3 # ×°±¸Ï´Á·×î´óÏ´Á·ÊôÐÔÌõÊý  | 
| g_allIndexList = [] #¿ÉÏ´Á¶µÄ²¿Î»»º´æ  | 
|   | 
| #def OnEquipWashLogin(curPlayer):  | 
| #    Sycn_EquipWashInfo(curPlayer, isLogin=True)  | 
| #    return  | 
|   | 
| def GetEquipWashMaxLV(curPlayer, equipPackindex, equipPlace):  | 
|     # @return: 0-먦·Å; >=1-¸Ã×°±¸Î»×î´ó¿ÉÏ´Á·µÈ¼¶  | 
|     washType = GetEquipWashType(equipPlace)  | 
|     if not washType:  | 
|         return 0  | 
|       | 
|     equipPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)  | 
|     curEquip = equipPack.GetAt(equipPackindex)  | 
|     if not curEquip or curEquip.IsEmpty():  | 
|         GameWorld.DebugLog("¸Ã×°±¸Î»Ã»ÓÐ×°±¸,ÎÞ·¨Ï´Á·£¡equipPackindex=%s" % (equipPackindex))  | 
|         return 0  | 
|       | 
|     equipStar = ChEquip.GetEquipPartStarByRank(curPlayer, equipPackindex, curEquip)  | 
|     ipyData = IpyGameDataPY.InterpolationSearch('ItemWashMax', 'Star', equipStar, {'Type':washType})  | 
|     if not ipyData:  | 
|         return 0  | 
|     return ipyData.GetLevelMax()  | 
|       | 
|       | 
|   | 
|   | 
| def GetEquipWashType(equipPlace):  | 
|     ## »ñȡװ±¸Î»¶ÔÓ¦µÄÏ´Á·ÀàÐÍ  | 
|     return IpyGameDataPY.GetFuncEvalCfg('EquipWashGroup', 1, {}).get(equipPlace)  | 
|       | 
|   | 
| def GetEquipWashData(washType, washLV):  | 
|     return IpyGameDataPY.GetIpyGameData("EquipWash", washType, washLV)  | 
|   | 
| def GetAllEquipWashPlace():  | 
|     # »ñÈ¡ËùÓпÉÏ´Á·µÄ×°±¸Î»  | 
|     global g_allIndexList  | 
|     if not g_allIndexList:  | 
|         maxClasslv = IpyGameDataPY.GetFuncCfg('EquipMaxClasslv')  | 
|         for equipPlace in IpyGameDataPY.GetFuncEvalCfg('EquipWashGroup', 1, {}):  | 
|             for classLV in xrange(1, maxClasslv+1):  | 
|                 ipyData = IpyGameDataPY.GetIpyGameData('EquipPlaceIndexMap', classLV, equipPlace)  | 
|                 if not ipyData:  | 
|                     continue  | 
|                 g_allIndexList.append(ipyData.GetGridIndex())  | 
|     return g_allIndexList  | 
|   | 
| #// A3 25 ×°±¸Ï´Á¶ #tagCMEquipXLAttrChange  | 
| #  | 
| #struct    tagCMEquipXLAttrChange  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        EquipPlace;    // ×°±¸Î»  | 
| #    BYTE        CheckUseGoldAttr;    // ¹´Ñ¡Ê¹ÓÃ×êʯϴÁ·ÊôÐÔ±àºÅÐÅÏ¢; °´ÊôÐÔ±àºÅλ¶þ½øÖÆ´ú±íÊÇ·ñ¹´Ñ¡  | 
| #                                        Èç¹´Ñ¡ÊôÐÔ1´ú±í0λ, Ôò·¢1, ¹´Ñ¡ÊôÐÔ1¡¢2Ôò·¢3£¬,¹´Ñ¡ÊôÐÔ1¡¢2¡¢3Ôò·¢7  | 
| #};  | 
| def OnEquipWashAttr(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     playerID = curPlayer.GetPlayerID()  | 
|       | 
|     equipPackindex = clientData.EquipPlace  | 
|     checkUseGoldAttr = clientData.CheckUseGoldAttr  | 
|     ipyData = IpyGameDataPY.GetIpyGameDataByCondition('EquipPlaceIndexMap', {'GridIndex':equipPackindex})  | 
|     if not ipyData:  | 
|         return  | 
|     equipPlace = ipyData.GetEquipPlace()  | 
|     classLV = ipyData.GetClassLV()  | 
|     funcPlusMinClassInfo = IpyGameDataPY.GetFuncEvalCfg("EquipPlusByFuncID", 1, {})  | 
|     funcID = ShareDefine.GameFuncID_EquipWash  | 
|     if str(funcID) in funcPlusMinClassInfo:  | 
|         funcMinClassLV = funcPlusMinClassInfo[str(funcID)]  | 
|         if classLV < funcMinClassLV:  | 
|             GameWorld.Log("¸Ã×°±¸½×ÎÞ·¨Ï´Á·! classLV=%s < funcMinClassLV=%s" % (classLV, funcMinClassLV), playerID)  | 
|             return  | 
|     washType = GetEquipWashType(equipPlace)  | 
|     if washType is None:  | 
|         GameWorld.Log("¸Ã×°±¸Î»ÎÞ·¨Ï´Á·! equipPlace=%s" % (equipPlace), playerID)  | 
|         return  | 
|       | 
|     maxWashLV = GetEquipWashMaxLV(curPlayer, equipPackindex, equipPlace)  | 
|     washLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % equipPackindex)  | 
|     GameWorld.DebugLog("×°±¸Ï´Á·: classLV=%s,equipPlace=%s,checkUseGoldAttr=%s,washType=%s,washLV=%s,maxWashLV=%s"   | 
|                        % (classLV, equipPlace, checkUseGoldAttr, washType, washLV, maxWashLV), playerID)  | 
|       | 
|     if maxWashLV < washLV:  | 
|         return  | 
|           | 
|     washData = GetEquipWashData(washType, washLV)  | 
|     if not washData:  | 
|         GameWorld.ErrLog("ÕÒ²»µ½¸Ã×°±¸Ï´Á·Êý¾Ý: washType=%s,washLV=%s" % (washType, washLV))  | 
|         return  | 
|       | 
|     maxValueAttrNumList = [] # ÒÑ´ïµ½µ±Ç°µÈ¼¶×î´óÖµµÄÊôÐÔ±àºÅÁÐ±í  | 
|     for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|         maxValue = getattr(washData, "GetAttrMax%s" % attrNum)()  | 
|         washValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|         washValueTemp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValueTemp % (equipPackindex, attrNum))  | 
|         if washValueTemp != 0:  | 
|             GameWorld.Log("»¹ÓÐδѡÔñÊÇ·ñ±£´æµÄÏ´Á·ÊôÐÔ£¬²»¿ÉÏ´Á·£¡equipPackindex=%s,attrNum=%s,washValueTemp=%s"   | 
|                           % (equipPackindex, attrNum, washValueTemp), playerID)  | 
|             return  | 
|         if washValue >= maxValue:  | 
|             maxValueAttrNumList.append(attrNum)  | 
|               | 
|     if washLV >= maxWashLV and len(maxValueAttrNumList) == Def_EquipWashMaxAttrCount:  | 
|         GameWorld.DebugLog("ËùÓÐÏ´Á·ÊôÐÔÒѾ´ïµ½×î´óÏ´Á·µÈ¼¶Öµ£¬ÎÞ·¨Ï´Á·£¡maxWashLV=%s" % maxWashLV, playerID)  | 
|         return  | 
|       | 
|     if len(maxValueAttrNumList) == Def_EquipWashMaxAttrCount:  | 
|         GameWorld.DebugLog("ËùÓÐÏ´Á·ÊôÐÔÒѾ´ïµ½±¾µÈ¼¶×î´óÖµ£¬ÇëÏÈÉý¼¶ºóÔÙÏ´Á·£¡maxWashLV=%s" % maxWashLV, playerID)  | 
|         return  | 
|       | 
|     costItemID = washData.GetCostItemID()  | 
|     costItemCount = washData.GetCostItemCount()  | 
|     costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID)  | 
|     if bindCnt + unBindCnt < costItemCount:  | 
|         GameWorld.DebugLog("×°±¸Ï´Á·ËùÐèÏûºÄµÀ¾ß²»×㣬ÎÞ·¨Ï´Á·!costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s"   | 
|                            % (costItemID, costItemCount, bindCnt, unBindCnt), playerID)  | 
|         return  | 
|       | 
|     goldWashCostItemCountList = washData.GetGoldWashCostList() # Ï´Á·±ØÔöÌõÊýÏûºÄ±ØÔöµÀ¾ß¸öÊý  | 
|     if not goldWashCostItemCountList or len(goldWashCostItemCountList) != Def_EquipWashMaxAttrCount:  | 
|         return  | 
|       | 
|     randAttrDict = {} # Ëæ»ú±ä¸üÖµ×Öµä {ÊôÐÔ±àºÅ:Ëæ»úÖµ, ...}  | 
|     useGoldAttrNumList = [] # Ê¹ÓÃ×êʯϴÁ·µÄÊôÐÔ±àºÅÁÐ±í  | 
|     negativeValueCnt = 0 # ¸ºÖµÊý, É趨º¬0°É£¬¼´·ÇÕýÊý  | 
|     fixMaxValueDict = {} # È«·þÐÞÕýÖµ×î´óÖµ×Öµä {ÊôÐÔ±àºÅ:×î´óÖµ, ...}  | 
|     for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|         if attrNum in maxValueAttrNumList:  | 
|             continue  | 
|           | 
|         washValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|         if checkUseGoldAttr & pow(2, attrNum - 1):  | 
|             useGoldAttrNumList.append(attrNum)  | 
|             randValueMin = getattr(washData, "GetAttrCostGoldMin%s" % attrNum)()  | 
|             randValueMax = getattr(washData, "GetAttrCostGoldMax%s" % attrNum)()  | 
|         else:  | 
|             randValueMin, randValueMax = 0, 0  | 
|             randDict = getattr(washData, "GetAttrRandDict%s" % attrNum)()  | 
|             for randKey, randRange in randDict.items():  | 
|                 if randKey[0] <= washValue <= randKey[1]:  | 
|                     randValueMin, randValueMax = randRange  | 
|                     break  | 
|             if not randValueMin and not randValueMax:  | 
|                 GameWorld.ErrLog("ÕÒ²»µ½¸Ã×°±¸Î»µ±Ç°Ï´Á·Öµ·¶Î§Ëæ»úÖµ!equipPackindex=%s,washType=%s,washLV=%s,attrNum=%s,washValue=%s,randDict=%s"   | 
|                                  % (equipPackindex, washType, washLV, attrNum, washValue, randDict))  | 
|                 return  | 
|         GameWorld.DebugLog("Ëæ»ú·¶Î§ÊôÐÔ%s, washValue=%s, %s~%s" % (attrNum, washValue, randValueMin, randValueMax))  | 
|         randValue = random.randint(randValueMin, randValueMax)  | 
|         for _ in xrange(50):  | 
|             if randValue != 0:  | 
|                 break  | 
|             randValue = random.randint(randValueMin, randValueMax)  | 
|             #GameWorld.DebugLog("Ëæ»úÖµ0£¬ÖØÐÂËæ»ú!")  | 
|         if randValue == 0:  | 
|             randValue = 1  | 
|             #GameWorld.DebugLog("Ëæ»úÖµ»¹ÊÇ0£¬Ç¿ÖÆÉèÖÃΪ1!")  | 
|         randAttrDict[attrNum] = randValue  | 
|         if randValue <= 0:  | 
|             negativeValueCnt += 1  | 
|         fixMaxValueDict[attrNum] = randValueMax  | 
|           | 
|     checkUseGoldCnt = len(useGoldAttrNumList)  | 
|     needGold = 0  | 
|     needMustID = IpyGameDataPY.GetFuncCfg("EquipWashMustID", 1)  | 
|     needMustIDCount = 0 if checkUseGoldCnt <= 0 else goldWashCostItemCountList[checkUseGoldCnt - 1]  | 
|     delMustIDCount = needMustIDCount  | 
|     mustItemIndexList, mustBindCnt, mustUnBindCnt = [], 0, 0  | 
|     if needMustIDCount:  | 
|         mustItemIndexList, mustBindCnt, mustUnBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, needMustID, needMustIDCount)  | 
|         mustItemLackCount = max(0, needMustIDCount - (mustBindCnt + mustUnBindCnt))  | 
|         if mustItemLackCount > 0:  | 
|             needGold = ItemCommon.GetAutoBuyItemNeedGold({needMustID:mustItemLackCount})  | 
|             if needGold <= 0:  | 
|                 GameWorld.ErrLog("×Ô¶¯¹ºÂò±ØÔöµÀ¾ßËùÐèÏÉÓñÒì³££¡needMustID=%s,mustItemLackCount=%s,needGold=%s"   | 
|                                  % (needMustID, mustItemLackCount, needGold), playerID)  | 
|                 return  | 
|             delMustIDCount = needMustIDCount - mustItemLackCount  | 
|               | 
|     if needGold and not PlayerControl.HaveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, needGold):  | 
|         GameWorld.DebugLog("ÏÉÓñ²»×㣬ÎÞ·¨Ï´Á·£¡checkUseGoldCnt=%s,needGold=%s" % (checkUseGoldCnt, needGold), playerID)  | 
|         return  | 
|       | 
|     preWashData = None # ÉÏһϴÁ·µÈ¼¶Êý¾Ý  | 
|     if washLV > 0:  | 
|         preWashData = GetEquipWashData(washType, washLV - 1)  | 
|         if not preWashData:  | 
|             GameWorld.ErrLog("ÕÒ²»µ½ÉÏÒ»¼¶Ï´Á·Êý¾Ý£¬ÎÞ·¨Ï´Á·!preWashLV=%s" % (washLV - 1))  | 
|             return  | 
|           | 
|     # ¿Û³ýÏûºÄ  | 
|     ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, costItemCount, "EquipWash")  | 
|     if delMustIDCount:  | 
|         ItemCommon.DelCostItemByBind(curPlayer, mustItemIndexList, mustBindCnt, mustUnBindCnt, delMustIDCount, "EquipWash")  | 
|           | 
|     if needGold:  | 
|         infoDict = {'classLV':classLV, "EquipPlace":equipPlace, "WashType":washType, "WashLV":washLV, "CheckUseGoldCnt":checkUseGoldCnt}  | 
|         PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, needGold, ChConfig.Def_Cost_EquipWash, infoDict)  | 
|           | 
|     GameWorld.DebugLog("Ëæ»úÏ´Á·: randAttrDict=%s,fixMaxValueDict=%s" % (randAttrDict, fixMaxValueDict), playerID)  | 
|     # È«¸ºÐÞÕý  | 
|     if negativeValueCnt == Def_EquipWashMaxAttrCount:  | 
|         minPer = 1  | 
|         minPerAttrNum = 1  | 
|         for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|             washValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|             preMaxValue = 0 if not preWashData else getattr(preWashData, "GetAttrMax%s" % attrNum)()  | 
|             curMaxValue = getattr(washData, "GetAttrMax%s" % attrNum)()  | 
|             curPer = (washValue - preMaxValue) / float(curMaxValue - preMaxValue)  | 
|             GameWorld.DebugLog("È«¸ºÐÞÕý±ÈÀý: attrNum=%s,curPer=%s" % (attrNum, curPer))  | 
|             if curPer < minPer:  | 
|                 minPer = curPer  | 
|                 minPerAttrNum = attrNum  | 
|                   | 
|         # µ±Ç°Ï´Á·±ÈÀýÖµ×îµÍµÄÐÞÕýΪÕýÊý  | 
|         fixValue = random.randint(1, fixMaxValueDict[minPerAttrNum])  | 
|         randAttrDict[minPerAttrNum] = fixValue  | 
|         GameWorld.DebugLog("È«¸ºÏ´Á·ÐÞÕý: minPerAttrNum=%s,minPer=%s,fixValue=%s,randAttrDict=%s"   | 
|                            % (minPerAttrNum, minPer, fixValue, randAttrDict), playerID)  | 
|           | 
|     # ×îÖÕÏ´Á·ÖµÈ·ÈÏ  | 
|     isRefreshAttr = False  | 
|     for attrNum, randValue in randAttrDict.items():  | 
|         washValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|         tempValue = washValue + randValue  | 
|         preMaxValue = 0 if not preWashData else getattr(preWashData, "GetAttrMax%s" % attrNum)()  | 
|         maxValue = getattr(washData, "GetAttrMax%s" % attrNum)()  | 
|         GameWorld.DebugLog("×îÖÕÏ´Á·ÖµÈ·ÈÏ: attrNum=%s,washValue=%s,randValue=%s,tempValue=%s,preMaxValue=%s,maxValue=%s"   | 
|                            % (attrNum, washValue, randValue, tempValue, preMaxValue, maxValue), playerID)  | 
|           | 
|         # ÏÂÏÞֵΪÉÏÒ»´ÎµÄÉÏÏÞÖµ  | 
|         if tempValue < preMaxValue:  | 
|             tempValue = preMaxValue  | 
|             GameWorld.DebugLog("    ÏÂÏÞÖµÐÞÕý: tempValue=%s" % tempValue, playerID)  | 
|               | 
|         # ×îºóÒ»¼¶µÄ»°¿É²»³¬¹ý×î´óÖµ£¬²»ÊÇ×îºóÒ»¼¶¿ÉÒç³ö  | 
|         if washLV == maxWashLV and tempValue > maxValue:  | 
|             tempValue = maxValue  | 
|             GameWorld.DebugLog("    ÉÏÏÞÖµÐÞÕý: maxValue=%s,tempValue=%s" % (maxValue, tempValue), playerID)  | 
|               | 
|         # Ê¹ÓÃ×êʯϴÁ·µÄÖ±½Ó¸üУ¬²»ÓÃÈ·ÈÏ  | 
|         if attrNum in useGoldAttrNumList:  | 
|             isRefreshAttr = True  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum), tempValue)  | 
|             dataDict = {'classLV':classLV, 'equipPlace':equipPlace,'attrNum':attrNum,'oldValue':washValue,'newValue':tempValue}  | 
|             DataRecordPack.Cache_FightPowerChangeInfo(curPlayer, ChConfig.PowerDownType_EquipWash, dataDict)  | 
|             GameWorld.DebugLog("    ¹´Ñ¡Ï´Á·£¬Ö±½Ó¸üÐÂÊýÖµ: %s" % tempValue, playerID)  | 
|         else:  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_EquipWashValueTemp % (equipPackindex, attrNum), tempValue)  | 
|               | 
|     #ÆÁ±Î×Ô¶¯Éý¼¶  | 
| #    if isRefreshAttr and washLV < maxWashLV:  | 
| #        CheckEquipWashLVUp(curPlayer, equipPlace, washLV, washData)  | 
|           | 
|     Sycn_EquipWashInfo(curPlayer, equipPackindex)  | 
|       | 
|     if isRefreshAttr:  | 
|         RefreshEquipWashAttr(curPlayer, classLV)  | 
|     PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_EquipWash, 1)  | 
|     PlayerActGarbageSorting.AddActGarbageTaskProgress(curPlayer, ChConfig.Def_GarbageTask_EquipWash)  | 
|     return  | 
|   | 
|   | 
| #// A3 26 ×°±¸Ï´Á¶½á¹ûÈ·ÈÏ #tagCMEquipXLAttrChangeOK  | 
| #  | 
| #struct    tagCMEquipXLAttrChangeOK  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        EquipPlace;    // ×°±¸Î»  | 
| #    BYTE        IsSave;        // ÊÇ·ñ±£´æ 0-·ñ; 1-ÊÇ; 2-ÊÖ¶¯Éý¼¶  | 
| #};  | 
| def OnEquipWashAttrChangeOK(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     playerID = curPlayer.GetPlayerID()  | 
|       | 
|     equipPackindex = clientData.EquipPlace  | 
|     isSave = clientData.IsSave  | 
|     ipyData = IpyGameDataPY.GetIpyGameDataByCondition('EquipPlaceIndexMap', {'GridIndex':equipPackindex})  | 
|     if not ipyData:  | 
|         return  | 
|     curPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)  | 
|     curEquip = curPack.GetAt(equipPackindex)  | 
|     if not curEquip or curEquip.IsEmpty():  | 
|         GameWorld.DebugLog("OnEquipWashAttrChangeOK() equip is empty")  | 
|         return  | 
|     equipPlace = ipyData.GetEquipPlace()  | 
|     classLV = ipyData.GetClassLV()  | 
|     washLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % equipPackindex)  | 
|     maxWashLV = GetEquipWashMaxLV(curPlayer, equipPackindex, equipPlace)  | 
|     GameWorld.DebugLog("È·ÈÏÏ´Á·½á¹û: classLV=%s, equipPlace=%s,isSave=%s,washLV=%s,maxWashLV=%s"   | 
|                        % (classLV, equipPlace, isSave, washLV, maxWashLV), playerID)  | 
|       | 
|     washType = GetEquipWashType(equipPlace)  | 
|     if washType is None:  | 
|         return  | 
|     if maxWashLV < 0:  | 
|         return  | 
|     washData = GetEquipWashData(washType, washLV)  | 
|     if not washData:  | 
|         return  | 
|       | 
|     # ÊÖ¶¯Éý¼¶  | 
|     if isSave == 2:  | 
|         if washLV >= maxWashLV:  | 
|             GameWorld.DebugLog("ÒÑ´ïµ½×î´óÏ´Á·µÈ¼¶£¬²»¿ÉÉý¼¶£¡", playerID)  | 
|             return  | 
|         if CheckEquipWashLVUp(curPlayer, curEquip, equipPackindex, washLV, washData):  | 
|             RefreshEquipWashAttr(curPlayer, classLV)  | 
|             Sycn_EquipWashInfo(curPlayer, equipPackindex)  | 
|             EquipWashSuccess(curPlayer, classLV)  | 
|         else:  | 
|             GameWorld.DebugLog("Éý¼¶Ê§°Ü£¬ÓÐÊôÐÔδ´ïµ½×î´óÖµ£¬ÎÞ·¨Éý¼¶!", playerID)  | 
|         return  | 
|       | 
|     for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|         tempValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValueTemp % (equipPackindex, attrNum))  | 
|         if not tempValue:  | 
|             continue  | 
|           | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_EquipWashValueTemp % (equipPackindex, attrNum), 0)  | 
|         if isSave == 1:  | 
|             oldValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum), tempValue)  | 
|             dataDict = {'classLV':classLV, 'equipPlace':equipPlace,'attrNum':attrNum,'oldValue':oldValue,'newValue':tempValue}  | 
|             DataRecordPack.Cache_FightPowerChangeInfo(curPlayer, ChConfig.PowerDownType_EquipWash, dataDict)  | 
|             GameWorld.DebugLog("±£´æÏ´Á·Êý¾Ý: classLV=%s, equipPlace=%s,attrNum=%s,tempValue=%s" % (classLV, equipPlace, attrNum, tempValue), playerID)  | 
|               | 
|     if isSave == 1:  | 
|         RefreshEquipWashAttr(curPlayer, classLV)  | 
|     #ÆÁ±Î×Ô¶¯Éý¼¶  | 
| #        if washLV < maxWashLV:  | 
| #            CheckEquipWashLVUp(curPlayer, equipPlace, washLV, washData)  | 
|     Sycn_EquipWashInfo(curPlayer, equipPackindex)  | 
|     return  | 
|   | 
| def CheckEquipWashLVUp(curPlayer, curEquip, equipPackindex, washLV, washData):  | 
|     # ¼ì²éÏ´Á·ÀàÐÍÉý¼¶  | 
|       | 
|     for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|         tempValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipPackindex, attrNum))  | 
|         # Ö»ÒªÓÐδ´ïµ½±¾¼¶×î´óÖµµÄ£¬Ôò²»ÄÜÉý¼¶  | 
|         if tempValue < getattr(washData, "GetAttrMax%s" % attrNum)():  | 
|             return  | 
|     washLV += 1  | 
|     SetEquipWashLV(curPlayer, equipPackindex, washLV)  | 
|       | 
|     # Ï´Á·¹ã²¥  | 
|     itemID = curEquip.GetItemTypeID()  | 
|     userData = curEquip.GetUserData()  | 
|     guid = ItemCommon.CacheNotifyEquipDetailInfo(curPlayer, curEquip)  | 
|     msgParamList = [curPlayer.GetPlayerName(), itemID, userData, guid, washLV]  | 
|     PlayerControl.WorldNotify(0, "WashCongratulation", msgParamList)  | 
|     return True  | 
|   | 
| def SetEquipWashLV(curPlayer, index, setWashLV):  | 
|     befWashLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % index)  | 
|     if befWashLV == setWashLV:  | 
|         return  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_EquipWashLV % (index), setWashLV)  | 
|       | 
|     # Í¬²½¸üÐÂÏ´Á·×ܵȼ¶  | 
|     befTotalWashLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TotalEquipWashLV)  | 
|     updTotalWashLV = max(0, befTotalWashLV + setWashLV - befWashLV)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TotalEquipWashLV, updTotalWashLV)  | 
|     GameWorld.DebugLog("ÉèÖÃÏ´Á·µÈ¼¶: index=%s,befWashLV=%s,setWashLV=%s,befTotalWashLV=%s,updTotalWashLV=%s"   | 
|                        % (index, befWashLV, setWashLV, befTotalWashLV, updTotalWashLV))  | 
|     return  | 
|   | 
| ## È«ÉíÏ´Á·×ܵȼ¶  | 
| def GetTotalEquipWashLV(curPlayer): return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TotalEquipWashLV)  | 
|   | 
| def Sycn_EquipWashInfo(curPlayer, equipPackindex=-1, isLogin=False):  | 
|     hasValue = False  | 
|       | 
|     pack = ChPyNetSendPack.tagMCEquipPartXLAttrInfo()  | 
|     pack.Clear()  | 
|     pack.InfoList = []  | 
|       | 
|     if equipPackindex == -1:  | 
|         syncPlaceList = GetAllEquipWashPlace()  | 
|     else:  | 
|         syncPlaceList = [equipPackindex]  | 
|           | 
|     for place in syncPlaceList:  | 
|         equipPart = ChPyNetSendPack.tagMCEquipPartXLAttr()  | 
|         equipPart.EquipPlace = place  | 
|         equipPart.XLAttrLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % place)  | 
|         equipPart.XLAttrList = []  | 
|         for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|             washValue = ChPyNetSendPack.tagMCEquipPartXLAttrValue()  | 
|             washValue.XLAttrValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (place, attrNum))  | 
|             washValue.XLAttrChange = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValueTemp % (place, attrNum))  | 
|             equipPart.XLAttrList.append(washValue)  | 
|             if washValue.XLAttrValue or washValue.XLAttrChange:  | 
|                 hasValue = True  | 
|                   | 
|         equipPart.XLAttrCnt = len(equipPart.XLAttrList)  | 
|         pack.InfoList.append(equipPart)  | 
|           | 
|     pack.Count = len(pack.InfoList)  | 
|       | 
|     # µÇ¼ͬ²½Ê±Èç¹ûûÓÐÏ´Á·ÊôÐÔÔò²»Í¬²½  | 
|     if isLogin and not hasValue:  | 
|         return  | 
|       | 
|     NetPackCommon.SendFakePack(curPlayer, pack)  | 
|     return  | 
|   | 
| def RefreshEquipWashAttr(curPlayer, classLV):  | 
|     ChEquip.RefreshPlayerEquipAttribute(curPlayer, classLV)  | 
|     #Ë¢ÐÂËùÓÐÊôÐÔ  | 
|     playControl = PlayerControl.PlayerControl(curPlayer)  | 
|     playControl.RefreshPlayerAttrState()  | 
|     return  | 
|   | 
| def CalcAttr_EquipWash(curPlayer, equipIndex, equipPlace, allAttrList):  | 
|     ## ×°±¸Î»Ï´Á·ÊôÐÔ  | 
|     washLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % equipIndex)  | 
|     maxWashLV = GetEquipWashMaxLV(curPlayer, equipIndex, equipPlace)  | 
|     washLV = min(washLV, maxWashLV)  | 
|     washType = GetEquipWashType(equipPlace)  | 
|     if washType is None:  | 
|         return  | 
|     washData = GetEquipWashData(washType, washLV)  | 
|     if not washData:  | 
|         return  | 
|     #GameWorld.DebugLog("×°±¸Î»ÊôÐÔ: equipPlace=%s,washLV=%s" % (equipPlace, washLV))  | 
|     for attrNum in range(1, Def_EquipWashMaxAttrCount + 1):  | 
|         attrID = getattr(washData, "GetAttrType%s" % attrNum)()  | 
|         maxValue = getattr(washData, "GetAttrMax%s" % attrNum)()  | 
|         attrValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashValue % (equipIndex, attrNum))  | 
|         attrValue = min(attrValue, maxValue)  | 
|         #GameWorld.DebugLog("    attrNum=%s,attrID=%s, attrValue=%s" % (attrNum, attrID, attrValue))  | 
|         if attrValue:  | 
|             PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)  | 
|     return  | 
|   | 
| def EquipWashSuccess(curPlayer, classLV):  | 
|     ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('EquipPlaceIndexMap', {'ClassLV':classLV}, True)  | 
|     if not ipyDataList:  | 
|         return  | 
|       | 
|     washLVCountDict = {}  | 
|     for ipyData in ipyDataList:  | 
|         index = ipyData.GetGridIndex()  | 
|         washLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_EquipWashLV % index)  | 
|         if not washLV:  | 
|             continue  | 
|         conditionKey = (classLV, washLV)  | 
|         washLVCountDict[conditionKey] = washLVCountDict.get(conditionKey, 0) + 1  | 
|           | 
|     #GameWorld.DebugLog("Ï´Á·³É¾ÍÊý¾Ý: classLV=%s,washLVCountDict=%s" % (classLV, washLVCountDict))  | 
|     PlayerSuccess.UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipWash, washLVCountDict)  | 
|     return  | 
|   |