#!/usr/bin/python  
 | 
# -*- coding: GBK -*-  
 | 
#-------------------------------------------------------------------------------  
 | 
#  
 | 
#-------------------------------------------------------------------------------  
 | 
#  
 | 
##@package Player.PlayerRune  
 | 
#  
 | 
# @todo:Íæ¼Ò·ûÓ¡  
 | 
# @author xdh  
 | 
# @date 2017-08-04  
 | 
# @version 1.0  
 | 
#  
 | 
# ÏêϸÃèÊö: Íæ¼Ò·ûÓ¡  
 | 
#---------------------------------------------------------------------  
 | 
#"""Version = 2017-08-04 12:00"""  
 | 
#---------------------------------------------------------------------  
 | 
  
 | 
import GameWorld  
 | 
import ShareDefine  
 | 
import ChConfig  
 | 
import ItemCommon  
 | 
import ItemControler  
 | 
import PlayerControl  
 | 
import ChPyNetSendPack  
 | 
import NetPackCommon  
 | 
import IpyGameDataPY  
 | 
import PlayerSuccess  
 | 
import PlayerMagicWeapon  
 | 
import IPY_GameWorld  
 | 
import OpenServerCampaign  
 | 
import DataRecordPack  
 | 
  
 | 
g_runeLVExpDict = {}  
 | 
  
 | 
##µÇ¼´¦Àí  
 | 
# @param curPlayer Íæ¼Ò  
 | 
# @return None  
 | 
def PlayerRuneLogin(curPlayer):  
 | 
    if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_VersionFix, ChConfig.Def_VerFix_RuneSource):  
 | 
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_VersionFix, ChConfig.Def_VerFix_RuneSource, 1)  
 | 
        runeHoleCnt = IpyGameDataPY.GetFuncCfg("RuneUnlock", 4)  
 | 
        for RuneNum in xrange(1, runeHoleCnt + 1):  
 | 
            RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % RuneNum, 0)  
 | 
            if not RuneData:  
 | 
                continue  
 | 
            RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('RuneCompound', RuneItemID)  
 | 
            if not ipyData:  
 | 
                continue  
 | 
            RuneSource = ItemControler.GetRuneItemSource(RuneData)  
 | 
            if RuneSource != ChConfig.Item_Source_Compound:  
 | 
                RuneItemPlusLV = ItemControler.GetRuneItemPlusLV(RuneData)  
 | 
                RuneIsLock = ItemControler.GetRuneItemIsLock(RuneData)  
 | 
                updRuneData = ItemControler.GetRuneItemKeyData(RuneItemID, RuneItemPlusLV, RuneIsLock, ChConfig.Item_Source_Compound)  
 | 
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_Data % RuneNum, updRuneData)  
 | 
                GameWorld.Log('ÉÏÏßÐÞ¸´Ë«ÊôÐÔ·ûÓ¡À´Ô´ RuneNum=%s,oldRuneData=%s,updRuneData=%s'%(RuneNum, RuneData, updRuneData))  
 | 
        packIndex = ShareDefine.rptRune  
 | 
        for place in xrange(ItemCommon.GetVPackCnt(packIndex)):  
 | 
            RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem % (packIndex, place))  
 | 
            if not RuneData:  
 | 
                continue  
 | 
            RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('RuneCompound', RuneItemID)  
 | 
            if not ipyData:  
 | 
                continue  
 | 
            RuneSource = ItemControler.GetRuneItemSource(RuneData)  
 | 
            if RuneSource != ChConfig.Item_Source_Compound:  
 | 
                RuneItemPlusLV = ItemControler.GetRuneItemPlusLV(RuneData)  
 | 
                RuneIsLock = ItemControler.GetRuneItemIsLock(RuneData)  
 | 
                updRuneData = ItemControler.GetRuneItemKeyData(RuneItemID, RuneItemPlusLV, RuneIsLock, ChConfig.Item_Source_Compound)  
 | 
                ItemControler.SetVPackItemKeyData(curPlayer, ShareDefine.rptRune, place, updRuneData)  
 | 
                GameWorld.Log('ÉÏÏßÐÞ¸´Ë«ÊôÐÔ·ûÓ¡À´Ô´ place=%s,oldRuneData=%s,updRuneData=%s'%(place, RuneData, updRuneData))  
 | 
      
 | 
      
 | 
    DoUnlockRuneHole(curPlayer, False)  
 | 
    Sync_RuneInfo(curPlayer)  
 | 
    return  
 | 
  
 | 
  
 | 
## »ñÈ¡·ûÓ¡ipyÊý¾Ý  
 | 
def GetRuneIpyData(itemID):return IpyGameDataPY.GetIpyGameData("Rune", itemID)  
 | 
  
 | 
## »ñÈ¡·ûÓ¡Éý¼¶ÐèÒª¾Ñé  
 | 
def GetRuneNeedExp(itemID, lv):  
 | 
    global g_runeLVExpDict  
 | 
    itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  
 | 
    if not itemData:  
 | 
        return 0  
 | 
    ipyData = GetRuneIpyData(itemID)  
 | 
    if not ipyData:  
 | 
        return 0  
 | 
    itemColor = itemData.GetItemColor()  
 | 
    if lv == 0: #³õʼ¾Ñé  
 | 
        expDict = IpyGameDataPY.GetFuncEvalCfg('RuneExp', 4, {})  
 | 
        exp = expDict.get(itemColor, 0)  
 | 
    else:  
 | 
        if lv in g_runeLVExpDict:  
 | 
            exp = g_runeLVExpDict[lv]  
 | 
        else:  
 | 
            level = lv + 1 #¹«Ê½´Ó1¿ªÊ¼  
 | 
            exp = eval(IpyGameDataPY.GetFuncCompileCfg('RuneExp'))  
 | 
            g_runeLVExpDict[lv] = exp  
 | 
              
 | 
        qualityPerDict = IpyGameDataPY.GetFuncEvalCfg('RuneExp', 2, {})  
 | 
        if itemColor in qualityPerDict:  
 | 
            exp *= float(qualityPerDict[itemColor])  
 | 
        if len(ipyData.GetAttrType()) > 1: #¶àÊôÐÔ  
 | 
            specialPer = IpyGameDataPY.GetFuncCfg('RuneExp', 3)  
 | 
            exp *= specialPer  
 | 
    return exp  
 | 
  
 | 
## »ñÈ¡·ûÓ¡ÊôÐÔÊýÖµ  
 | 
def GetRuneAttrValue(itemID, lv):  
 | 
    itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  
 | 
    if not itemData:  
 | 
        return {}  
 | 
    ipyData = GetRuneIpyData(itemID)  
 | 
    if not ipyData:  
 | 
        return {}  
 | 
    level = lv + 1 #¹«Ê½´Ó1¿ªÊ¼  
 | 
      
 | 
    attrTypeList = ipyData.GetAttrType()  
 | 
    isSpecial = len(attrTypeList) > 1 #ÊÇ·ñ¶àÊôÐÔ  
 | 
    itemColor = itemData.GetItemColor()  
 | 
    attrDict = {}  
 | 
    for attrType in attrTypeList:  
 | 
        keyStr = 'RuneAttr%s' % attrType  
 | 
        attrFormula = IpyGameDataPY.GetFuncCompileCfg(keyStr)  
 | 
        if not attrFormula:  
 | 
            continue  
 | 
          
 | 
        value = eval(attrFormula)  
 | 
        qualityPerDict = IpyGameDataPY.GetFuncEvalCfg(keyStr, 2, {})  
 | 
        if itemColor in qualityPerDict:  
 | 
            value *= float(qualityPerDict[itemColor])  
 | 
        if isSpecial:  
 | 
            specialPer = IpyGameDataPY.GetFuncCfg(keyStr, 3)  
 | 
            if specialPer:  
 | 
                value *= specialPer  
 | 
            else:  
 | 
                GameWorld.ErrLog(' itemID=%s   ¹¦ÄÜÅäÖñíkeyStr=%s, ÊýÖµ3δÅäÖÃ' % (itemID, keyStr))  
 | 
        attrDict[int(attrType)] = int(value)  
 | 
    return attrDict  
 | 
  
 | 
def GetRuneMaxLV(itemID):  
 | 
    # »ñÈ¡·ûÓ¡×î´óµÈ¼¶  
 | 
    itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  
 | 
    if not itemData:  
 | 
        return 0  
 | 
    runeMaxLVDict = IpyGameDataPY.GetFuncEvalCfg('RuneMaxLV', 1, {})  
 | 
    itemColor = itemData.GetItemColor()  
 | 
    runeMaxLV = runeMaxLVDict.get(itemColor, 0)  
 | 
    return runeMaxLV  
 | 
  
 | 
#// A5 13 ½âËø·ûÓ¡¿× #tagCMUnlockRuneHole  
 | 
#  
 | 
#struct    tagCMUnlockRuneHole  
 | 
#{  
 | 
#    tagHead        Head;  
 | 
#    BYTE        HoleIndex; // ¿×Ë÷Òý  
 | 
#};  
 | 
def OnUnlockRuneHole(index, clientData, tick):  
 | 
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  
 | 
    holeIndex = clientData.HoleIndex  
 | 
    runeUnlockDict = IpyGameDataPY.GetFuncEvalCfg("RuneUnlock", 2, {})  
 | 
    if holeIndex not in runeUnlockDict:  
 | 
        return  
 | 
    runeOpenState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_HoleOpenState, 0)  
 | 
    if runeOpenState & pow(2, holeIndex):  
 | 
        return  
 | 
    if curPlayer.GetLV() < IpyGameDataPY.GetFuncEvalCfg("RuneUnlock", 3, {}).get(holeIndex, 0):  
 | 
        return  
 | 
    costMoney = runeUnlockDict[holeIndex]  
 | 
    if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costMoney, ChConfig.Def_Cost_RuneHole, {'holeIndex':holeIndex}):  
 | 
        return  
 | 
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_HoleOpenState, runeOpenState |pow(2, holeIndex))  
 | 
    Sync_RuneInfo(curPlayer)  
 | 
    PlayerControl.WorldNotify(0, 'RuneSpecialHoleGet', [curPlayer.GetName(), costMoney])  
 | 
    return  
 | 
  
 | 
def DoUnlockRuneHole(curPlayer, isSycn=True):  
 | 
    # ½âËø·ûÓ¡¿×, ·ûÓ¡Ëþ¹ý¹ØÊ±µ÷Óà  
 | 
    runeUnlockList = IpyGameDataPY.GetFuncEvalCfg("RuneUnlock")  
 | 
      
 | 
    runeOpenState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_HoleOpenState, 0)  
 | 
    trialTowerPassLV = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_TrialTower_PassLV) # ·ûÓ¡ËþÒѹý¹Ø²ãÊý  
 | 
    updOpenState = runeOpenState  
 | 
    for holeNum, needTowerPassLV in enumerate(runeUnlockList):  
 | 
        if runeOpenState & pow(2, holeNum):  
 | 
            continue  
 | 
          
 | 
        if trialTowerPassLV < needTowerPassLV:  
 | 
            continue  
 | 
        updOpenState |= pow(2, holeNum)  
 | 
        GameWorld.DebugLog('    ½âËø·ûÓ¡¿× holeNum=%s,trialTowerPassLV=%s' % (holeNum, trialTowerPassLV))  
 | 
    if updOpenState != runeOpenState:  
 | 
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_HoleOpenState, updOpenState)  
 | 
        if isSycn:  
 | 
            Sync_RuneInfo(curPlayer)  
 | 
    return  
 | 
  
 | 
## »ñÈ¡·ûÓ¡ÊÇ·ñÒѽâËø  
 | 
def GetIsOpenByRuneID(curPlayer, itemid):  
 | 
    itemData = GameWorld.GetGameData().GetItemByTypeID(itemid)  
 | 
    if not itemData:  
 | 
        return  
 | 
    curPassLV = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_TrialTower_PassLV)  
 | 
    curEff = itemData.GetEffectByIndex(0)  
 | 
    curRuneType = curEff.GetEffectID()  
 | 
    floorCnt = IpyGameDataPY.GetFuncCfg('TowerRuneType', 2)  
 | 
    towerRuneTypeDict = IpyGameDataPY.GetFuncEvalCfg('TowerRuneType')  
 | 
    floorList = [int(i) for i in towerRuneTypeDict]  
 | 
    floorList.sort()  
 | 
    for floor in floorList:  
 | 
        typeList = towerRuneTypeDict[str(floor)]  
 | 
        if curRuneType in typeList:  
 | 
            floorkey = (int(floor) - 1)*100+ floorCnt if int(floor) > 1 else 0  
 | 
            return curPassLV >= floorkey  
 | 
    # Ã»ÅäÖÃÏÞÖÆ²ãÊý½âËøµÄĬÈϽâËø  
 | 
    return True  
 | 
  
 | 
def SwitchRune(curPlayer, srcBackpack, desBackPack, srcIndex, destIndex):  
 | 
    # ÏâǶ/ժϷûÓ¡  
 | 
    if not ((desBackPack == ShareDefine.rptRune and srcBackpack == ShareDefine.rptTempSwap) \  
 | 
            or (srcBackpack == ShareDefine.rptRune and desBackPack == ShareDefine.rptTempSwap)):  
 | 
        return False  
 | 
      
 | 
  
 | 
    maxRuneHole = IpyGameDataPY.GetFuncCfg("RuneUnlock", 4)  
 | 
    # ´©  
 | 
    if desBackPack == ShareDefine.rptTempSwap:  
 | 
        desRuneNum = destIndex + 1  
 | 
        if desRuneNum < 1 or desRuneNum > maxRuneHole:  
 | 
            GameWorld.DebugLog("²»´æÔڸ÷ûÓ¡¿×! desRuneNum=%s" % desRuneNum, curPlayer.GetPlayerID())  
 | 
            return True  
 | 
          
 | 
        runeOpenState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_HoleOpenState, 0)  
 | 
        if not runeOpenState & pow(2, destIndex):  
 | 
            GameWorld.DebugLog("¸Ã·ûÓ¡¿×δ½âËø! desRuneNum=%s,state=%s" % (desRuneNum, runeOpenState), curPlayer.GetPlayerID())  
 | 
            return True  
 | 
          
 | 
        srcRuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem   
 | 
                                                     % (ShareDefine.rptRune, srcIndex)) # ·ûÓ¡±³°üÖеÄÖµ  
 | 
        if not srcRuneData:  
 | 
            GameWorld.DebugLog("·ûÓ¡±³°ü¸ÃλÖÃûÓзûÓ¡! srcIndex=%s" % srcIndex, curPlayer.GetPlayerID())  
 | 
            return True  
 | 
        srcRuneItemID = ItemControler.GetRuneItemID(srcRuneData)  
 | 
          
 | 
        srcIpyData = GetRuneIpyData(srcRuneItemID)  
 | 
          
 | 
        if not srcIpyData:  
 | 
            GameWorld.DebugLog("¸Ã·ûӡûÓÐÅäÖÃÊôÐÔ! ÎÞ·¨ÏâǶ! itemID=%s" % srcRuneItemID, curPlayer.GetPlayerID())  
 | 
            return True  
 | 
        srcRuneAttrType = srcIpyData.GetAttrType()  
 | 
        # ÅжÏÊÇ·ñÒÑÓÐÏâǶ¸ÃÊôÐÔÀàÐÍ  
 | 
        doubleCnt = 0 #Ë«ÊôÐÔ·ûÓ¡¸öÊý  
 | 
        for RuneNum in xrange(1, maxRuneHole + 1):  
 | 
            if RuneNum == desRuneNum: # Ä¿±ê¿×²»ÅÐ¶Ï  
 | 
                continue  
 | 
            RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % RuneNum, 0)  
 | 
            if not RuneData:  
 | 
                continue  
 | 
            RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
            ipyData = GetRuneIpyData(RuneItemID)  
 | 
            if not ipyData:  
 | 
                continue  
 | 
            attrTypeList = ipyData.GetAttrType()  
 | 
            if srcRuneAttrType == attrTypeList:  
 | 
                GameWorld.DebugLog("ÒÑÓÐÏâǶ¸ÃÊôÐÔÀàÐÍ! ÎÞ·¨ÏâǶ! RuneHoleNum=%s,srcRuneAttrType=%s" % (RuneNum, srcRuneAttrType), curPlayer.GetPlayerID())  
 | 
                return True  
 | 
            if len(attrTypeList) > 1:  
 | 
                doubleCnt +=1  
 | 
          
 | 
        if len(srcRuneAttrType) > 1 and doubleCnt >= __GetCanInlayDoubleAttrRuneCnt(curPlayer):  
 | 
            GameWorld.DebugLog("µ±Ç°¿ÉÏâǶ˫ÊôÐÔ·ûÓ¡¸öÊýÒÑ´ïÉÏÏÞ%s! ÎÞ·¨ÏâǶ! itemID=%s" % (doubleCnt, srcRuneItemID), curPlayer.GetPlayerID())  
 | 
            return True  
 | 
          
 | 
        desRuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % desRuneNum, 0) # ¿×ÉϵÄÖµ  
 | 
          
 | 
        # ÉèÖ÷ûÓ¡¿×Êý¾Ý  
 | 
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_Data % desRuneNum, srcRuneData)  
 | 
        # ÔÀ´µÄ¿×Êý¾Ý£¬Ôò·ÅÈë·ûÓ¡±³°üÖÐ  
 | 
        ItemControler.SetVPackItemKeyData(curPlayer, ShareDefine.rptRune, srcIndex, desRuneData)  
 | 
        #·ûÓ¡³É¾Í  
 | 
        DoRuneSuccessLogic(curPlayer)  
 | 
    else:  
 | 
        srcRuneNum = srcIndex + 1  
 | 
        srcRuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % srcRuneNum, 0)  
 | 
        if not srcRuneData:  
 | 
            GameWorld.DebugLog("¸Ã·ûÓ¡¿×ûÓÐÏâǶ·ûÓ¡! srcRuneNum=%s, srcRuneData=%s" % (srcRuneNum, srcRuneData), curPlayer.GetPlayerID())  
 | 
            return True  
 | 
          
 | 
        emptyIndex = ItemCommon.GetEmptyIndexInPack(curPlayer, ShareDefine.rptRune)  
 | 
        if emptyIndex == -1:  
 | 
            GameWorld.DebugLog("·ûÓ¡±³°üÒÑÂú£¬ÎÞ·¨ÕªÏÂ! ", curPlayer.GetPlayerID())  
 | 
            return True  
 | 
        desRuneData = 0  
 | 
        # ÕªÏÂÉèÖÿ×Êý¾ÝΪ0  
 | 
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_Data % srcRuneNum, 0)  
 | 
        ItemControler.SetVPackItemKeyData(curPlayer, ShareDefine.rptRune, emptyIndex, srcRuneData)  
 | 
    dataDict = {'desBackPack':desBackPack, 'srcRuneData':srcRuneData, 'desRuneData':desRuneData}  
 | 
    DataRecordPack.Cache_FightPowerChangeInfo(curPlayer, ChConfig.PowerDownType_Rune, dataDict)  
 | 
    RefreshRuneAttr(curPlayer)  
 | 
    PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()  
 | 
    Sync_RuneInfo(curPlayer)  
 | 
    return True  
 | 
  
 | 
def __GetCanInlayDoubleAttrRuneCnt(curPlayer):  
 | 
    ##µ±Ç°¿ÉÏâǶ¼¸¸öË«ÊôÐÔ·ûÓ¡  
 | 
    runeDoubleInlayCntDict = IpyGameDataPY.GetFuncEvalCfg('RuneDoubleInlayCnt', 1, {})  
 | 
    trialTowerPassLV = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_TrialTower_PassLV) # ·ûÓ¡ËþÒѹý¹Ø²ãÊý  
 | 
    sortLVList = sorted(runeDoubleInlayCntDict.keys())  
 | 
    findLV = 0  
 | 
    for plv in sortLVList:  
 | 
        if trialTowerPassLV < plv:  
 | 
            break  
 | 
        findLV = plv  
 | 
    return runeDoubleInlayCntDict.get(findLV, 0)  
 | 
  
 | 
#// A5 65 ·ûÓ¡Éý¼¶ #tagCMRuneUp  
 | 
#  
 | 
#struct    tagCMRuneUp  
 | 
#{  
 | 
#    tagHead        Head;  
 | 
#    BYTE        PlaceType;    // Î»ÖÃÀàÐÍ£»0-·ûÓ¡±³°ü£¬1-·ûÓ¡¿×  
 | 
#    WORD        PlaceIndex;    // Î»ÖÃË÷Òý  
 | 
#};  
 | 
def OnRuneUp(index, clientData, tick):  
 | 
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  
 | 
    placeType = clientData.PlaceType  
 | 
    placeIndex = clientData.PlaceIndex  
 | 
      
 | 
    if placeType == 0:  
 | 
        RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem % (ShareDefine.rptRune, placeIndex))  
 | 
    elif placeType == 1:  
 | 
        RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % (placeIndex + 1), 0)  
 | 
    else:  
 | 
        return  
 | 
      
 | 
    playerID = curPlayer.GetPlayerID()  
 | 
    if not RuneData:  
 | 
        GameWorld.DebugLog("¸ÃλÖò»´æÔÚ·ûÓ¡, ÎÞ·¨Éý¼¶! placeType=%s,placeIndex=%s" % (placeType, placeIndex), playerID)  
 | 
        return  
 | 
      
 | 
    RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
    RuneItemPlusLV = ItemControler.GetRuneItemPlusLV(RuneData)  
 | 
    RuneIsLock = ItemControler.GetRuneItemIsLock(RuneData)  
 | 
    RuneSource = ItemControler.GetRuneItemSource(RuneData)  
 | 
    itemData = GameWorld.GetGameData().GetItemByTypeID(RuneItemID)  
 | 
    if not itemData:  
 | 
        return  
 | 
      
 | 
    runeMaxLV = GetRuneMaxLV(RuneItemID)  
 | 
    if RuneItemPlusLV + 1 >= runeMaxLV:  
 | 
        GameWorld.DebugLog('¸Ã·ûÓ¡ÒÑÂú¼¶£¬ÎÞ·¨Éý¼¶£¡runeMaxLV=%s' % runeMaxLV)  
 | 
        return  
 | 
      
 | 
    plusCost = GetRuneNeedExp(RuneItemID, RuneItemPlusLV + 1)  
 | 
    plusCost = int(plusCost)  
 | 
    if not plusCost:  
 | 
        GameWorld.DebugLog("¸Ã·ûÓ¡ÎÞ·¨Éý¼¶!  placeType=%s,placeIndex=%s,itemID=%s,plusLV=%s"   
 | 
                           % (placeType, placeIndex, RuneItemID, RuneItemPlusLV), playerID)  
 | 
        return  
 | 
  
 | 
      
 | 
    updRuneData = ItemControler.GetRuneItemKeyData(RuneItemID, RuneItemPlusLV + 1, RuneIsLock, RuneSource)  
 | 
    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_Rune, plusCost):  
 | 
        curRuneMoney = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_Rune)  
 | 
        GameWorld.DebugLog("·ûÓ¡¾«»ªµã²»×㣬ÎÞ·¨Éý¼¶!placeType=%s,placeIndex=%s,itemID=%s,plusLV=%s,plusCost=%s,curRuneMoney=%s"   
 | 
                           % (placeType, placeIndex, RuneItemID, RuneItemPlusLV, plusCost, curRuneMoney), playerID)  
 | 
        return  
 | 
      
 | 
    if placeType == 0:  
 | 
        ItemControler.SetVPackItemKeyData(curPlayer, ShareDefine.rptRune, placeIndex, updRuneData)  
 | 
    elif placeType == 1:  
 | 
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_Data % (placeIndex + 1), updRuneData)  
 | 
        RefreshRuneAttr(curPlayer)  
 | 
        PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()  
 | 
        Sync_RuneInfo(curPlayer)  
 | 
        DoRuneSuccessLogic(curPlayer)  
 | 
          
 | 
    #itemData = GameWorld.GetGameData().GetItemByTypeID(RuneItemID)  
 | 
    #RuneName = RuneItemID if not itemData else "%s(%s)" % (itemData.GetName(), RuneItemID)  
 | 
    #aftRuneMoney = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_Rune)  
 | 
    #EventReport.WriteEvent_rune_lv(curPlayer, RuneName, plusCost, RuneItemPlusLV + 1, aftRuneMoney)  
 | 
    GameWorld.DebugLog("·ûÓ¡Éý¼¶!placeType=%s,placeIndex=%s,RuneData=%s,updRuneData=%s"   
 | 
                       % (placeType, placeIndex, RuneData, updRuneData), playerID)  
 | 
    return  
 | 
  
 | 
  
 | 
def DoRuneSuccessLogic(curPlayer):  
 | 
    #·ûÓ¡³É¾Í´¦Àí  
 | 
    #Çåµô#ÏâǶXöXÆ·ÖÊ·ûÓ¡µÄ³É¾ÍÐÅÏ¢  
 | 
    PlayerSuccess.ResetSuccessByType(curPlayer, ShareDefine.SuccType_InlayRune)  
 | 
    totalLV = 0  
 | 
    runeHoleCnt = IpyGameDataPY.GetFuncCfg("RuneUnlock", 4)  
 | 
    for holeNum in xrange(1, runeHoleCnt + 1):  
 | 
        runeData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % holeNum, 0)  
 | 
        if not runeData:  
 | 
            continue  
 | 
        runeItemID = ItemControler.GetRuneItemID(runeData)  
 | 
        itemData = GameWorld.GetGameData().GetItemByTypeID(runeItemID)  
 | 
        if not itemData:  
 | 
            continue  
 | 
        itemColor = itemData.GetItemColor()  
 | 
        runeItemPlusLV = ItemControler.GetRuneItemPlusLV(runeData) + 1 #¿Í»§¶Ë1¿ªÊ¼  
 | 
        totalLV += runeItemPlusLV  
 | 
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_InlayRune, 1, [itemColor])  
 | 
    PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_RuneLvUp, totalLV)  
 | 
    # ¿ª·þ»î¶¯Êý¾Ý  
 | 
    OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_RuneLV, totalLV)  
 | 
    return  
 | 
  
 | 
#// A5 66 ·ûÓ¡·Ö½â #tagCMRuneDecompose  
 | 
#  
 | 
#struct    tagCMRuneDecompose  
 | 
#{  
 | 
#    tagHead        Head;  
 | 
#    BYTE        IsAll;    // ÊÇ·ñÈ«²¿·Ö½â£¬ÓÅÏȼ¶×î¸ß£¬Ëø¶¨³ýÍâ  
 | 
#    BYTE        QualityCnt;    // °´È«²¿·Ö½âÆ·ÖÊÊý  
 | 
#    BYTE        QualityList[QualityCnt];    // È«²¿·Ö½âµÄÆ·ÖÊÁÐ±í£¬·¢ËÍµÄÆ·ÖÊ»áÈ«²¿·Ö½â£¬Ëø¶¨³ýÍâ  
 | 
#    BYTE        Count;    // Ö¸¶¨ÅúÁ¿·Ö½âÊý£¬×î´ó²»³¬¹ý50¸ö  
 | 
#    WORD        PlaceIndexList[Count];    // ÅúÁ¿·Ö½âλÖÃË÷ÒýÁÐ±í  
 | 
#};  
 | 
def OnRuneDecompose(index, clientData, tick):  
 | 
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  
 | 
    isAll = clientData.IsAll  
 | 
    qualityList = clientData.QualityList  
 | 
    GameWorld.DebugLog("·ûÓ¡·Ö½â: isAll=%s,qualityList=%s,PlaceIndexList=%s" % (isAll, qualityList, clientData.PlaceIndexList))  
 | 
      
 | 
    delPlaceDict = {}  
 | 
    totalDecompose = 0  
 | 
    totalMJ = 0  
 | 
    packIndex = ShareDefine.rptRune  
 | 
    placeList = xrange(ItemCommon.GetVPackCnt(packIndex)) if (isAll or clientData.QualityCnt > 0) else clientData.PlaceIndexList  
 | 
    wmpIpyData = PlayerMagicWeapon.GetMagicWeaponPrivilege(curPlayer, ChConfig.MWPrivilege_RuneDecompose)  
 | 
    addPer = int(wmpIpyData.GetEffectValue()) if wmpIpyData else 0  
 | 
    for place in placeList:  
 | 
        RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem % (packIndex, place))  
 | 
        if not RuneData:  
 | 
            continue  
 | 
        # Ëø¶¨µÄ²»¿É·Ö½â  
 | 
        RuneIsLock = ItemControler.GetRuneItemIsLock(RuneData)  
 | 
        if RuneIsLock:  
 | 
            continue  
 | 
        RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
        RuneItemPlusLV = ItemControler.GetRuneItemPlusLV(RuneData)  
 | 
        itemData = GameWorld.GetGameData().GetItemByTypeID(RuneItemID)  
 | 
        if not itemData:  
 | 
            continue  
 | 
          
 | 
        quality = itemData.GetItemColor()  
 | 
          
 | 
        if not (isAll or quality in qualityList or place in clientData.PlaceIndexList):  
 | 
            continue  
 | 
          
 | 
        if itemData.GetType() == ChConfig.Def_ItemType_RuneExp: #¾«»ªÎïÆ·¶ÁЧ¹ûÖµ  
 | 
            curEff = itemData.GetEffectByIndex(0)  
 | 
            decompose = curEff.GetEffectValue(0)  
 | 
            decompose += decompose * addPer / ShareDefine.Def_MaxRateValue  
 | 
        else:  
 | 
            decompose = 0  
 | 
            for lv in range(RuneItemPlusLV + 1):  
 | 
                decompose += GetRuneNeedExp(RuneItemID, lv)  
 | 
                if lv == 0:  
 | 
                    decompose += decompose * addPer / ShareDefine.Def_MaxRateValue  
 | 
                      
 | 
            ipyData = IpyGameDataPY.GetIpyGameDataNotLog('RuneCompound', RuneItemID)  
 | 
            if ipyData and ItemControler.GetRuneItemSource(RuneData) in [ChConfig.Rune_Source_Unkown,ChConfig.Item_Source_Compound]:  
 | 
                totalMJ += ipyData.GetNeedMJ()  
 | 
              
 | 
  
 | 
        totalDecompose += decompose  
 | 
        delPlaceDict[place] = [RuneData, int(decompose)]  
 | 
          
 | 
    if delPlaceDict:  
 | 
        ItemCommon.DelVPackItem(curPlayer, packIndex, delPlaceDict.keys(), ChConfig.ItemDel_Rune)  
 | 
      
 | 
    totalDecompose = int(totalDecompose)  
 | 
    if totalDecompose:  
 | 
        addDataDict = {"delPlaceDict":delPlaceDict, "totalDecompose":totalDecompose}  
 | 
        PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_Rune, totalDecompose,   
 | 
                                ChConfig.Def_GiveMoney_RuneDecompose, addDataDict, False)  
 | 
        PlayerControl.NotifyCode(curPlayer, 'hwj_20170807_1', [totalDecompose, ShareDefine.TYPE_Price_Rune])  
 | 
    if totalMJ:  
 | 
        addDataDict = {"delPlaceDict":delPlaceDict, "totalMJ":totalMJ}  
 | 
        PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_Ysog, totalMJ,   
 | 
                                ChConfig.Def_GiveMoney_RuneDecompose, addDataDict, False)  
 | 
        PlayerControl.NotifyCode(curPlayer, 'hwj_20170807_1', [totalMJ, ShareDefine.TYPE_Price_Ysog])  
 | 
    return  
 | 
  
 | 
#// A5 67 ·ûÓ¡Ëø¶¨×´Ì¬±ä¸ü #tagCMRuneLock  
 | 
#  
 | 
#struct    tagCMRuneLock  
 | 
#{  
 | 
#    tagHead        Head;  
 | 
#    BYTE        LockState;    // Ëø¶¨×´Ì¬£¬ 0-Ëø¶¨£¬1-½âËø  
 | 
#    BYTE        Count;    // ÅúÁ¿²Ù×÷Êý£¬×î´ó²»³¬¹ý50¸ö  
 | 
#    WORD        PlaceIndexList[Count];    // ÅúÁ¿²Ù×÷λÖÃË÷ÒýÁÐ±í  
 | 
#};  
 | 
def OnRuneLock(index, clientData, tick):  
 | 
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  
 | 
    packIndex = ShareDefine.rptRune  
 | 
    changeLockState = clientData.LockState # Ëø¶¨×´Ì¬£¬ 1-Ëø¶¨£¬0-½âËø  
 | 
      
 | 
    changePlaceList = []  
 | 
    for place in clientData.PlaceIndexList:  
 | 
        RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem % (packIndex, place))  
 | 
        if not RuneData:  
 | 
            continue  
 | 
        RuneIsLock = ItemControler.GetRuneItemIsLock(RuneData)  
 | 
        if changeLockState == RuneIsLock:  
 | 
            continue  
 | 
        RuneItemID = ItemControler.GetRuneItemID(RuneData)  
 | 
        RuneItemPlusLV = ItemControler.GetRuneItemPlusLV(RuneData)  
 | 
        updRuneData = ItemControler.GetRuneItemKeyData(RuneItemID, RuneItemPlusLV, changeLockState)  
 | 
        ItemControler.SetVPackItemKeyData(curPlayer, packIndex, place, updRuneData, False)  
 | 
        changePlaceList.append(place)  
 | 
          
 | 
    if changePlaceList:  
 | 
        ItemControler.Sync_VPackItem_Refresh(curPlayer, packIndex, changePlaceList)  
 | 
        GameWorld.DebugLog("Ð޸ķûÓ¡Ëø¶¨×´Ì¬: changeLockState=%s, %s" % (changeLockState, changePlaceList))  
 | 
    return  
 | 
  
 | 
#// A5 78 ·ûÓ¡ºÏ³É #tagCMRuneCompound  
 | 
#  
 | 
#struct    tagCMRuneCompound  
 | 
#  
 | 
#{  
 | 
#    tagHead        Head;  
 | 
#    BYTE        Cnt;  
 | 
#    BYTE        PackList[Cnt];    //ËùÔÚλÖà0-±³°ü 1-·ûÓ¡¿×  
 | 
#    BYTE        IndexList[Cnt];    //ÎïÆ·Ë÷Òý  
 | 
#    DWORD        TagItemID;    //ºÏ³ÉÄ¿±êÎïÆ·ID  
 | 
#};  
 | 
def OnRuneCompound(index, clientData, tick):  
 | 
    ##·ûÓ¡ºÏ³É  
 | 
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  
 | 
    tagItemID = clientData.TagItemID  
 | 
    packList = clientData.PackList  
 | 
    indexList = clientData.IndexList  
 | 
    GameWorld.DebugLog('    ·ûÓ¡ºÏ³É tagItemID=%s'%tagItemID)  
 | 
    ipyData = IpyGameDataPY.GetIpyGameData('RuneCompound', tagItemID)  
 | 
    if not ipyData:  
 | 
        return  
 | 
    materialsIDList = []  
 | 
    materialsLVDict = {}  
 | 
    indexList1 = [] #±³°üµÄ·ûÓ¡Ë÷Òý  
 | 
    indexList2 = [] #¿×Ë÷Òý  
 | 
    for i, placeType in enumerate(packList):  
 | 
        index = indexList[i]  
 | 
        if placeType == 0:  
 | 
            runeData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_VPackItem % (ShareDefine.rptRune, index)) # ·ûÓ¡±³°üÖеÄÖµ  
 | 
            indexList1.append(index)  
 | 
        else:  
 | 
            runeData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % (index+1), 0)  
 | 
            indexList2.append(index+1)  
 | 
        if not runeData:  
 | 
            continue  
 | 
        runeItemID = ItemControler.GetRuneItemID(runeData)  
 | 
        runeItemPlusLV = ItemControler.GetRuneItemPlusLV(runeData)  
 | 
        materialsIDList.append(runeItemID)   
 | 
        materialsLVDict[runeItemID] = runeItemPlusLV  
 | 
          
 | 
      
 | 
    needItemIDList = ipyData.GetNeedItem()  
 | 
    if sorted(materialsIDList) != sorted(needItemIDList):  
 | 
        GameWorld.DebugLog('    ·ûÓ¡ºÏ³É ²ÄÁϲ»¶Ô tagItemID=%s, materialsIDList=%s, needItemIDList=%s'%(tagItemID,materialsIDList,needItemIDList))  
 | 
        return  
 | 
      
 | 
    if 0 not in packList:  
 | 
        #Èç¹ûûÓб³°üµÄ²ÄÁÏÒªÅжϸñ×ÓÊý  
 | 
        emptySpace = ItemCommon.GetItemPackSpace(curPlayer, ShareDefine.rptRune, 1)  
 | 
        if emptySpace < 1:  
 | 
            PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_676165", [ShareDefine.rptRune])  
 | 
            GameWorld.DebugLog('    ·ûÓ¡ºÏ³É ±³°ü¸ñ×ÓÊýÁ¿²»×ã1¸ö')  
 | 
            return   
 | 
          
 | 
    needMJ = ipyData.GetNeedMJ()  
 | 
    infoDict = {"TagItemID":tagItemID}  
 | 
    if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_Ysog, needMJ, ChConfig.Def_Cost_ItemProduce, infoDict):  
 | 
        return  
 | 
       
 | 
    totalPoint = 0  
 | 
    for itemID in materialsIDList:  
 | 
        decompose = 0  
 | 
        RuneItemPlusLV = materialsLVDict.get(itemID,0)  
 | 
        for lv in range(1, RuneItemPlusLV + 1):  
 | 
            decompose += GetRuneNeedExp(itemID, lv)  
 | 
        totalPoint += decompose  
 | 
    totalPoint = int(totalPoint)  
 | 
    tagItemLV = 0  
 | 
  
 | 
    runeMaxLV = GetRuneMaxLV(tagItemID)  
 | 
    for lv in xrange(1, runeMaxLV):  
 | 
        needExp = GetRuneNeedExp(tagItemID, lv)  
 | 
        if totalPoint < needExp:  
 | 
            break  
 | 
        tagItemLV = lv  
 | 
        totalPoint -= needExp  
 | 
      
 | 
    #ɾ³ý²ÄÁÏÎïÆ·  
 | 
    if indexList1:  
 | 
        ItemCommon.DelVPackItem(curPlayer, ShareDefine.rptRune, indexList1, ChConfig.ItemDel_Rune)  
 | 
    if indexList2:  
 | 
        for index in indexList2:  
 | 
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Rune_Data % index, 0)  
 | 
        Sync_RuneInfo(curPlayer)  
 | 
        RefreshRuneAttr(curPlayer)  
 | 
        PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()  
 | 
          
 | 
    #¸øÐÂÎïÆ·  
 | 
    curItem = ItemControler.GetOutPutItemObj(tagItemID)  
 | 
    curItem.SetUserAttr(ShareDefine.Def_IudetRuneLV, tagItemLV)  
 | 
    curItem.SetUserAttr(ShareDefine.Def_IudetRuneSource, ChConfig.Item_Source_Compound)  
 | 
    PlayerItemControler = ItemControler.PlayerItemControler(curPlayer)  
 | 
    PlayerItemControler.PutInItem(ShareDefine.rptRune, curItem, event=[ChConfig.ItemGive_RuneCompound, False, {'indexList1':indexList1,'indexList2':indexList2}])  
 | 
    curPlayer.Sync_MakeItemAnswer(ShareDefine.Def_mitRuneCompound, 1)  
 | 
    return  
 | 
  
 | 
  
 | 
## Ë¢·ûÓ¡ÊôÐÔ  
 | 
def RefreshRuneAttr(curPlayer):  
 | 
    allAttrList = [{} for _ in range(4)]  
 | 
    runeHoleCnt = IpyGameDataPY.GetFuncCfg("RuneUnlock", 4)  
 | 
    for holeNum in xrange(1, runeHoleCnt + 1):  
 | 
        runeData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % holeNum, 0)  
 | 
        if not runeData:  
 | 
            continue  
 | 
        runeItemID = ItemControler.GetRuneItemID(runeData)  
 | 
        runeItemPlusLV = ItemControler.GetRuneItemPlusLV(runeData)  
 | 
          
 | 
        attrDict = GetRuneAttrValue(runeItemID, runeItemPlusLV)  
 | 
          
 | 
        if not attrDict:  
 | 
            continue  
 | 
        GameWorld.DebugLog('    Ë¢·ûÓ¡ÊôÐÔ holeNum=%s, attrDict=%s' % (holeNum, attrDict))  
 | 
        for attrID, attrValue in attrDict.items():  
 | 
            PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)  
 | 
          
 | 
    # ±£´æ¼ÆËãÖµ  
 | 
    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Rune, allAttrList)  
 | 
    return  
 | 
  
 | 
  
 | 
  
 | 
## Í¬²½¿Í»§¶Ë  
 | 
def Sync_RuneInfo(curPlayer):  
 | 
    runeHoleCnt = IpyGameDataPY.GetFuncCfg("RuneUnlock", 4)  
 | 
    if not runeHoleCnt:  
 | 
        return  
 | 
    RuneInfoPack = ChPyNetSendPack.tagMCRuneInfo()  
 | 
    RuneInfoPack.Clear()  
 | 
    RuneInfoPack.RuneHoleOpenState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_HoleOpenState, 0)  
 | 
    RuneInfoPack.RuneDataList = []  
 | 
    for RuneNum in xrange(1, runeHoleCnt + 1):  
 | 
        RuneData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Rune_Data % RuneNum, 0)  
 | 
        RuneInfoPack.RuneDataList.append(RuneData)  
 | 
    RuneInfoPack.Count = len(RuneInfoPack.RuneDataList)  
 | 
    NetPackCommon.SendFakePack(curPlayer, RuneInfoPack)  
 | 
    return  
 |