| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package Player.PlayerPet  | 
| #  | 
| # @todo:³èÎï/ÁéÊÞ  | 
| # @author xdh  | 
| # @date 2018-7-20  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ³èÎï  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2018-7-20 15:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| #µ¼Èë  | 
| import ChConfig  | 
| import NPCCommon  | 
| import ItemCommon  | 
| import IPY_GameWorld  | 
| import DataRecordPack  | 
| import PlayerBillboard  | 
| import SkillShell  | 
| import ItemControler  | 
| import PlayerControl  | 
| import PlayerSuccess  | 
| import GameFuncComm  | 
| import ShareDefine  | 
| import SkillCommon  | 
| import PetControl  | 
| import EventShell  | 
| import GameWorld  | 
| import IpyGameDataPY  | 
| import PlayerAttrFruit  | 
| import OpenServerCampaign  | 
| import PlayerWeekParty  | 
| import CalcNoLineEffect  | 
| import CalcLineEffect  | 
| import PlayerActivity  | 
| import ChPyNetSendPack  | 
| import NetPackCommon  | 
| import PlayerActHorsePetTrain  | 
| import PlayerActTask  | 
|   | 
| import random  | 
| import math  | 
|   | 
|   | 
| def DoLogic_PetInfo_OnDay(curPlayer):  | 
|     return  | 
|   | 
| def OnPlayerPetLogin(curPlayer):  | 
|     ## µÇ¼´¦Àí  | 
|     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Pet):  | 
|         return  | 
|       | 
|     # ÅàÑøÊǺóÃæ¼ÓµÄ¹¦ÄÜ£¬Ã¿´ÎµÇ¼²¹¼ì²éһϹ¦ÄÜ¿ªÊ¼Ê±ÉèÖÃΪÅàÑø1¼¶  | 
|     for trainType in xrange(1, GetPetTrainTypes() + 1):  | 
|         if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainLV % trainType) == 0:  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PetTrainLV % trainType, 1)  | 
|               | 
|     Sync_PetTrainData(curPlayer)  | 
|     return  | 
|   | 
| def DoPetOpen(curPlayer):  | 
|     GameWorld.DebugLog("DoPetOpen...", curPlayer.GetPlayerID())  | 
|       | 
|     for trainType in xrange(1, GetPetTrainTypes() + 1):  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PetTrainLV % trainType, 1)  | 
|     Sync_PetTrainData(curPlayer)  | 
|     return True  | 
|   | 
| ## ¹¦ÄÜ¿ªÆôºó, ½ÇÉ«Éý¼¶ÐèÒªµÄ´¦Àí  | 
| def DoLVUPLogic_Pet(curPlayer):  | 
|     #GameWorld.DebugLog("DoLVUPLogic_Pet")  | 
|     return  | 
|   | 
| def GetPetIpydata(petNPCID):return IpyGameDataPY.GetIpyGameData("PetInfo", petNPCID)  | 
|   | 
| ## »ñȡгèÎïÊý¾ÝÎïÆ·  | 
| def GetNewPetDataItem(curPlayer, petNPCID, classlv= -1):  | 
|   | 
|     gameData = GameWorld.GetGameData()  | 
|     petNpcData = gameData.FindNPCDataByID(petNPCID)  | 
|     if not petNpcData:  | 
|         GameWorld.ErrLog("FindNPCDataByID can not find npcData petNPCID=%s" % (petNPCID))  | 
|         return  | 
|     petIpyData = GetPetIpydata(petNPCID)  | 
|     if not petIpyData:  | 
|         GameWorld.ErrLog("tagPetInfo.txt can not find petData petNPCID=%s" % (petNPCID))  | 
|         return  | 
|       | 
|     newPetItem = ItemCommon.CreateSingleItem(ChConfig.Def_ItemID_PetData)  | 
|     if not newPetItem:  | 
|         return  | 
|       | 
|     newPetItem.SetUserAttr(ShareDefine.Def_IudetPet_NPCID, petNPCID)  | 
|     newPetItem.SetUserAttr(ShareDefine.Def_IudetPet_State, 0)  | 
|       | 
|     initClass = petIpyData.GetInitRank() if classlv == -1 else classlv#³õʼ½×¼¶  | 
|     newPetItem.SetUserAttr(ShareDefine.Def_IudetPet_ClassLV, max(0, initClass - 1)) #´úÂëÀï´Ó0¿ªÊ¼  | 
|     newPetItem.SetUserAttr(ShareDefine.Def_IudetPet_QualityLV, petIpyData.GetQuality()) # ³èÎïÆ·ÖÊ  | 
|       | 
|     __UpdPetItemSkillByClass(curPlayer, newPetItem, False)      | 
|     return newPetItem  | 
|   | 
| ## »ñÈ¡³èÎïʵÀý¶ÔÓ¦µÄ³èÎïÊý¾ÝÎïÆ·  | 
| def GetPetDataItem(curPetOwner, rolePet):  | 
|     if not curPetOwner:  | 
|         return  | 
|     packItemIndex = GetPetDataItemByNPCID(curPetOwner, rolePet.GetNPCID())  | 
|     return GetPetDataItemByIndex(curPetOwner, packItemIndex)  | 
|   | 
| ## »ñÈ¡³èÎïÊý¾ÝÎïÆ·  | 
| def GetPetDataItemByIndex(curPlayer, petItemIndex):  | 
|       | 
|     petDataPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptPet)  | 
|     if petItemIndex < 0 or petItemIndex >= petDataPack.GetCount():  | 
|         return  | 
|     petDataItem = petDataPack.GetAt(petItemIndex)  | 
|     if not ItemCommon.CheckItemCanUse(petDataItem):  | 
|         GameWorld.DebugLog("PetDataItem is none! PetItemIndex=%s" % petItemIndex, curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     return petDataItem  | 
|   | 
| ## »ñÈ¡³èÎïÊý¾ÝÎïÆ·  | 
| def GetPetDataItemByNPCID(curPlayer, petNPCID):  | 
|     petDataPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptPet)  | 
|     for petDataIndex in range(petDataPack.GetCount()):  | 
|         petItem = petDataPack.GetAt(petDataIndex)  | 
|         if petItem.IsEmpty():  | 
|             continue  | 
|         if petNPCID == petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID):  | 
|             return petItem  | 
|     return  | 
|   | 
| ## ¸ù¾Ý³èÎïNPCID»ñÈ¡³èÎïÊý¾ÝÎïÆ·ÔÚ±³°üÖеÄË÷Òý  | 
| def GetPetDataItemIndexByNPCID(curPlayer, petNPCID):  | 
|     petDataPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptPet)  | 
|     for petDataIndex in range(petDataPack.GetCount()):  | 
|         petItem = petDataPack.GetAt(petDataIndex)  | 
|         if petItem.IsEmpty():  | 
|             continue  | 
|         if petNPCID == petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID):  | 
|             return petDataIndex  | 
|           | 
|     return -1  | 
|   | 
| def GetPetItemCacheDict(petItem):  | 
|     ## µ¥¸öÁé³èÎïÆ·»º´æÐÅÏ¢  | 
|     npcID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|     state = petItem.GetUserAttr(ShareDefine.Def_IudetPet_State)  | 
|     classLV = petItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV)  | 
|     quality = petItem.GetUserAttr(ShareDefine.Def_IudetPet_QualityLV)  | 
|     star = petItem.GetUserAttr(ShareDefine.Def_IudetPet_Star)  | 
|     skills = [petItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, i) for i in xrange(petItem.GetUserAttrCount(ShareDefine.Def_IudetPet_Skill))]  | 
|     cacheDict = {"npcID":npcID}  | 
|     state and cacheDict.update({"state":state})  | 
|     classLV and cacheDict.update({"classLV":classLV})  | 
|     quality and cacheDict.update({"quality":quality})  | 
|     star and cacheDict.update({"star":star})  | 
|     skills and cacheDict.update({"skills":skills})  | 
|     return cacheDict  | 
|   | 
| def GetPetCacheInfo(curPlayer):  | 
|     ## »ñÈ¡Áé³è¹¦ÄÜ»º´æÐÅÏ¢£¬ÔÝʱ»º´æÈ«²¿£¬Èç¹ûÓÐÐèÒª¸ÄΪ½ö»º´æÉÏÕóµÄ  | 
|     itemCacheList = []  | 
|     petDataPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptPet)  | 
|     for petDataIndex in range(petDataPack.GetCount()):  | 
|         petItem = petDataPack.GetAt(petDataIndex)  | 
|         if petItem.IsEmpty():  | 
|             continue  | 
|         itemCacheList.append(GetPetItemCacheDict(petItem))  | 
|     return itemCacheList  | 
|   | 
| # //16 03 ³èÎï³öÕ½/ÕÙ»Ø#tagCPetStateChange  | 
| # tagCPetStateChange       *   GettagCPetStateChange();  | 
| #   | 
| # class   IPY_CPetStateChange  | 
| # {  | 
| # public:  | 
| #   | 
| #    int      GetPetID();  | 
| #    // ×´Ì¬.0-ÕÙ»Ø;1-³öÕ½;2xx-ÊØ»¤(ÊØ»¤+Ä¿±êÊØ»¤Î»)  | 
| #    int      GetState(); 0~255  | 
| # };  | 
| def PetStateChange(index, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     pack = IPY_GameWorld.IPY_CPetStateChange()  | 
|     petItemIndex = pack.GetPetID()  | 
|     state = pack.GetState()  | 
|     DoChangePetState(curPlayer, petItemIndex, state)  | 
|     return  | 
|   | 
| ## ³èÎïÕ½¶·×´Ì¬±ä¸ü; 0-Êջأ»1-³öÕ½  (ÊÖÓΰ汾ֻÄܳöÕ½)  | 
| def DoChangePetState(curPlayer, petItemIndex, tagState):  | 
|     # @param tagState: 0-Êջأ»>=1-³öÕ½ÔÚµÚ¼¸¸öλÖà  | 
|       | 
|     petItem = GetPetDataItemByIndex(curPlayer, petItemIndex)  | 
|     if not petItem:  | 
|         return  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     petNPCID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|     curState = petItem.GetUserAttr(ShareDefine.Def_IudetPet_State)  | 
|     GameWorld.DebugLog("³èÎï״̬±ä¸ü! petItemIndex=%s,petNPCID=%s,curState=%s,tagState=%s"   | 
|                        % (petItemIndex, petNPCID, curState, tagState), playerID)  | 
|     # ÊÕ»Ø  | 
|     if tagState <= 0:  | 
|         SetPetState(curPlayer, petItem, tagState)  | 
|         return  | 
|       | 
|     gooutFightRealmList = IpyGameDataPY.GetFuncEvalCfg("PetGoOutFight", 1)  | 
|     if tagState > len(gooutFightRealmList):  | 
|         GameWorld.DebugLog("    ²»´æÔÚ¸ÃÁé³èÉÏÕóλÖÃ! tagState=%s" % tagState, playerID)  | 
|         return  | 
|     needRealmLV = gooutFightRealmList[tagState - 1]  | 
|     curRealmLV = curPlayer.GetOfficialRank()  | 
|     if curRealmLV < needRealmLV:  | 
|         GameWorld.DebugLog("    ¾³½ç²»×㣬ÎÞ·¨ÉÏÕóÁéÊÞ! curRealmLV=%s < %s, tagState=%s" % (curRealmLV, curRealmLV, tagState), playerID)  | 
|         return  | 
|       | 
|     #ÅжÏÊÇ·ñ´ïµ½¿ÉÇл»µÄ½×Êý  | 
|     curClasslv = petItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV)  | 
|     ipyData = GetPetIpydata(petNPCID)  | 
|     if not ipyData:  | 
|         return  | 
|     needClasslv = ipyData.GetUseNeedRank()  | 
|     if curClasslv < needClasslv - 1: #ÅäÖõĽ׼¶´Ó1¿ªÊ¼  | 
|         GameWorld.DebugLog('    ÁéÊÞÇл»Íâ¹Û,½×¼¶²»×ã%s,²»¿ÉÇл»£¡' % needClasslv, playerID)  | 
|         return  | 
|     SetPetState(curPlayer, petItem, tagState)  | 
|     return  | 
|   | 
| def SetPetState(curPlayer, petItem, tagState):  | 
|     ## ÉèÖÃÁé³è³öս״̬  | 
|     # @param tagState: 0-Êջأ»>=1-³öÕ½ÔÚµÚ¼¸¸öλÖà  | 
|     npcID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|     if tagState <= 0:  | 
|         GameWorld.DebugLog("    Áé³èÏÂÕó: npcID=%s" % npcID, curPlayer.GetPlayerID())  | 
|     else:  | 
|         petDataPack = curPlayer.GetItemManager().GetPack(ShareDefine.rptPet)  | 
|         for index in range(petDataPack.GetCount()):  | 
|             item = petDataPack.GetAt(index)  | 
|             if item.IsEmpty():  | 
|                 continue  | 
|             if item.GetUserAttr(ShareDefine.Def_IudetPet_State) == tagState:  | 
|                 SetPetState(curPlayer, item, 0)  | 
|         GameWorld.DebugLog("    Áé³èÉÏÕó: npcID=%s,tagState=%s" % (npcID, tagState), curPlayer.GetPlayerID())  | 
|     petItem.SetUserAttr(ShareDefine.Def_IudetPet_State, tagState)  | 
|     return  | 
|   | 
| def CrossServer_DoChangePetState(curPlayer, dataList):  | 
|     ## ¿ç·þ´¦Àí ³èÎïÕ½¶·×´Ì¬±ä¸ü  | 
|     return  | 
|   | 
| def AutoSummonPet(curPlayer):  | 
|     return  | 
|   | 
| ## »ñÈ¡³öÕ½³èÎïҪѧµÄ¼¼ÄÜ  | 
| def GetPetLearnSkill(curPlayer):  | 
|     learnSkillDict = {}  | 
|     passiveSkillList = []  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         petItem = petPack.GetAt(i)  | 
|         if petItem.IsEmpty():  | 
|             continue  | 
|         for i in range(petItem.GetUserAttrCount(ShareDefine.Def_IudetPet_Skill)):  | 
|             skillID = petItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, i)  | 
|             curSkilData = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|             if not curSkilData:  | 
|                 continue  | 
|             if SkillCommon.isPassiveAttr(curSkilData):  | 
|                 #±»¶¯¼¼ÄÜÊôÐÔ²»Ñ§  | 
|                 passiveSkillList.append(skillID)  | 
|                 continue  | 
|             skillTypeID = curSkilData.GetSkillTypeID()  | 
|             if skillTypeID in learnSkillDict:  | 
|                 learnSkillDict[skillTypeID].append(skillID)  | 
|             else:  | 
|                 learnSkillDict[skillTypeID] = [skillID]  | 
|               | 
|     learnSkillIDList = [max(a) for a in learnSkillDict.values()]  | 
|     return learnSkillIDList, passiveSkillList  | 
|       | 
| #===============================================================================  | 
| #// A7 02 ³èÎD»î #tagCMActivatePet  | 
| #  | 
| #struct    tagCMActivatePet  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        PetNPCID; // ³èÎïNPCID  | 
| #    BYTE        IsUseGold; // ÊÇ·ñʹÓÃ×êʯֱ½Ó¹ºÂò¼¤»î  | 
| #};  | 
| def OnActivatePet(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     petNPCID = clientData.PetNPCID  | 
|     isUseGold = clientData.IsUseGold  | 
|     DoActivatePet(curPlayer, petNPCID, isUseGold, True)  | 
|     return  | 
|   | 
| def DoActivatePet(curPlayer, petNPCID, isUseGold=False, isUseItem=False):  | 
|     if not isUseItem:  | 
|         #ĿǰֻÄÜÎïÆ·¼¤»î  | 
|         return  | 
|       | 
|     hasSpace = False  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         packItem = petPack.GetAt(i)  | 
|         if packItem.IsEmpty():  | 
|             hasSpace = True  | 
|             continue  | 
|           | 
|         petItemNPCID = packItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         if petItemNPCID == petNPCID:  | 
|             GameWorld.DebugLog("ÒѾӵÓиóèÎ i=%s,petItemNPCID=%s,petNPCID=%s" % (i, petItemNPCID, petNPCID))  | 
|             return  | 
|       | 
|     if not hasSpace:  | 
|         PlayerControl.NotifyCode(curPlayer, "Pet_liubo_76326") # ³èÎïÊýÁ¿´ïµ½ÉÏÏÞ  | 
|         return  | 
|     ipyData = GetPetIpydata(petNPCID)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     needItemID = ipyData.GetUnLockNeedItemID()  | 
|     needItemCnt = ipyData.GetUnLockNeedItemCnt()  | 
|     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)  | 
|     hasEnough, itemList = ItemCommon.GetItem_FromPack_ByID(needItemID, itemPack, needItemCnt)  | 
|     if not hasEnough:  | 
|         GameWorld.DebugLog("DoActivatePet() item(%s[%s]) isn't enough" % (needItemID, needItemCnt))  | 
|         return  | 
|       | 
|     newPetItem = GetNewPetDataItem(curPlayer, petNPCID)  | 
|     if not newPetItem:  | 
|         return  | 
|       | 
|     if not ItemControler.PlayerItemControler(curPlayer).PutInItem(petPackIndex, newPetItem):  | 
|         return  | 
|       | 
|     ItemCommon.ReduceItem(curPlayer, itemPack, itemList, needItemCnt, False, ChConfig.ItemDel_Pet)  | 
|           | 
|     EventShell.EventRespons_OnActivatePet(curPlayer, petNPCID)  | 
|     sysMark = ipyData.GetUnlockSys() or 'GetPet'  | 
|     PlayerControl.WorldNotify(0, sysMark, [curPlayer.GetName(), petNPCID])  | 
|       | 
|     RefreshPetItemAddAttr(curPlayer, True)  | 
|       | 
|     # ¿ª·þ»î¶¯Êý¾Ý  | 
|     OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_PetLV, GetTotalPetLV(curPlayer))  | 
|     PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_Pet, petNPCID, False)  | 
|     return True  | 
|   | 
|   | 
| def DoPetActivate(curPlayer, index, classlv=None, refresh=True):  | 
|     ##Ö±½Ó¼¤»î Íⲿµ÷ÓÃGM²âÊÔÓà  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     petInfoCount = ipyDataMgr.GetPetInfoCount()  | 
|     if petInfoCount <= 0 or index > petInfoCount:  | 
|         GameWorld.ErrLog("¼¤»î³èÎﳬ¹ý³èÎï±íÊý¾ÝÊý: index=%s,petInfoCount=%s" % (index, petInfoCount))  | 
|         return  | 
|     petIpyData = ipyDataMgr.GetPetInfoByIndex(index - 1)  | 
|     petNPCID = petIpyData.GetID()  | 
|     quality = petIpyData.GetQuality()  | 
|     maxClassLV = petIpyData.GetMaxRank()  | 
|       | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         packItem = petPack.GetAt(i)  | 
|         if packItem.IsEmpty():  | 
|             continue  | 
|         petItemNPCID = packItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         if petItemNPCID == petNPCID:  | 
|             if classlv:  | 
|                 packItem.SetUserAttr(ShareDefine.Def_IudetPet_ClassLV, max(0, min(classlv, maxClassLV) - 1))  | 
|             packItem.SetUserAttr(ShareDefine.Def_IudetPet_QualityLV, quality) # ³èÎïÆ·ÖÊ  | 
|             GameWorld.DebugLog("ÒѾӵÓиóèÎ i=%s,petItemNPCID=%s,petNPCID=%s" % (i, petItemNPCID, petNPCID))  | 
|             __UpdPetItemSkillByClass(curPlayer, packItem, True)  | 
|             return True  | 
|           | 
|     if classlv == None:  | 
|         classlv = 1  | 
|     classlv = min(classlv, maxClassLV)  | 
|     newPetItem = GetNewPetDataItem(curPlayer, petNPCID, classlv)  | 
|     if not newPetItem:  | 
|         return  | 
|     petPackIndex = ShareDefine.rptPet  | 
|       | 
|     if not ItemControler.PlayerItemControler(curPlayer).PutInItem(petPackIndex, newPetItem):  | 
|         return  | 
|     if not refresh:  | 
|         return True  | 
|     RefreshPetItemAddAttr(curPlayer, True)  | 
|     return True  | 
|   | 
| #// A7 04 ³èÎïÉý½× #tagCMPetClassUP  | 
| #  | 
| #struct    tagCMPetClassUP  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        PetItemIndex;    //³èÎïÊý¾Ý±³°üË÷Òý  | 
| #};  | 
| def PetClassUp(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Pet):  | 
|         GameWorld.DebugLog(' ³èÎ﹦ÄÜ먦Æô')  | 
|         return  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     PetItemIndex = clientData.PetItemIndex  | 
|     costItemCount = clientData.UseItemCnt # ÏûºÄ²ÄÁϸöÊý  | 
|     isAutoBuy = 0 #clientData.IsAutoBuy # ÊÇ·ñ×Ô¶¯¹ºÂò  | 
|     petDataItem = GetPetDataItemByIndex(curPlayer, PetItemIndex)  | 
|     if not petDataItem:  | 
|         return  | 
|       | 
|     petNPCID = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|   | 
|     petNpcData = GameWorld.GetGameData().FindNPCDataByID(petNPCID)  | 
|     if not petNpcData:  | 
|         GameWorld.ErrLog("can not found pet npcID = %s" % (petNPCID))  | 
|         return  | 
|       | 
|     classLV = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV)  | 
|     petIpyData = GetPetIpydata(petNPCID)  | 
|     if not petIpyData:  | 
|         return  | 
|     maxClassLV = petIpyData.GetMaxRank()  | 
|     if classLV + 2 > maxClassLV:  | 
|         GameWorld.DebugLog("³èÎïÉý½× ÒÑÂú¼¶¡£¡£¡£classLV=%s" % classLV, playerID)  | 
|         return  | 
|       | 
|     ipyData = IpyGameDataPY.GetIpyGameData("PetClassCost", petNPCID, classLV + 1)  | 
|     if not ipyData:  | 
|         return  | 
|       | 
|     needExp = ipyData.GetUpNeedExp()  | 
|     if not needExp:  | 
|         return  | 
|       | 
|     curPetClassExp = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_Exp)  | 
|       | 
|       | 
|     curItemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)  | 
|       | 
|     itemIndexList = []  | 
|     costItemIDList = []  | 
|     specCostItemInfo = IpyGameDataPY.GetFuncEvalCfg('PetUpItem', 4)  | 
|     for strItemID, petNPCIDList in specCostItemInfo.items():  | 
|         if petNPCID in petNPCIDList:  | 
|             costItemIDList = [int(strItemID)]  | 
|             break  | 
|     if not costItemIDList:  | 
|         costItemIDList = IpyGameDataPY.GetFuncEvalCfg('PetUpItem')  | 
|     if not costItemIDList:  | 
|         return  | 
|       | 
|     #¿Û²ÄÁÏ  | 
|     nowCnt = 0  | 
|     for itemID in costItemIDList:  | 
|         hasEnough, indexList, findItemIsBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(itemID, curItemPack, costItemCount - nowCnt)  | 
|         itemIndexList.extend(indexList)  | 
|         if hasEnough:  | 
|             #×ã¹»Í˳ö  | 
|             break  | 
|         if itemIndexList:  | 
|             nowCnt = 0  | 
|             for itemIndex in itemIndexList:  | 
|                 curItem = curItemPack.GetAt(itemIndex)  | 
|                 #¼ì²éÎïÆ·  | 
|                 if not ItemCommon.CheckItemCanUse(curItem):  | 
|                     continue  | 
|                 itemCnt = curItem.GetCount()  | 
|                 nowCnt += itemCnt  | 
|     if not hasEnough and not isAutoBuy:  | 
|         GameWorld.DebugLog("PetClassUp Éý½×µÀ¾ß²»×ã! petNPCID=%s,costItemIDList=%s" % (petNPCID, costItemIDList))  | 
|         return  | 
|       | 
|     autoBuyItemID = costItemIDList[0]  | 
|     if itemIndexList:  | 
|         curItem = curItemPack.GetAt(itemIndexList[0])  | 
|     else:  | 
|         curItem = GameWorld.GetGameData().GetItemByTypeID(autoBuyItemID)  | 
|     if not curItem:  | 
|         return  | 
|       | 
|     if lackCnt > 0:  | 
|         return  | 
|       | 
|     playerName = curPlayer.GetName()  | 
|      | 
|     curEff = curItem.GetEffectByIndex(0)  | 
|     addExp = curEff.GetEffectValue(0) * costItemCount  | 
|     updExp = curPetClassExp + addExp  | 
|     updClassLV = classLV  | 
|     for lv in xrange(classLV, maxClassLV - 1):  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("PetClassCost", petNPCID, lv + 1)  | 
|         if not ipyData:  | 
|             break  | 
|         upNeedExp = ipyData.GetUpNeedExp()  | 
|         if updExp < upNeedExp:  | 
|             break  | 
|         updExp -= upNeedExp  | 
|         updClassLV += 1  | 
|           | 
|       | 
|     #¿Û³ýÎïÆ·  | 
|     delCnt = max(0, costItemCount - lackCnt) # Êµ¼Ê¿Û³ýµÄ¸öÊý  | 
|     if itemIndexList:  | 
|         ItemCommon.ReduceItem(curPlayer, curItemPack, itemIndexList, delCnt, True, ChConfig.ItemDel_Pet)  | 
|           | 
|     # ¸üоÑéÖµ  | 
|     if updClassLV + 1 >= maxClassLV:  | 
|         updExp = 0  | 
|     petDataItem.SetUserAttr(ShareDefine.Def_IudetPet_Exp, updExp)  | 
|     if updClassLV > classLV:  | 
|         petDataItem.SetUserAttr(ShareDefine.Def_IudetPet_ClassLV, updClassLV)  | 
|           | 
|         learnSkillList = __UpdPetItemSkillByClass(curPlayer, petDataItem, True)  | 
|           | 
|         if not learnSkillList and updClassLV + 1 == maxClassLV:  | 
|             PlayerControl.WorldNotify(0, 'PetUpLvMax', [playerName, petNPCID])  | 
|         # Èç¹ûÊǵ±Ç°³öÕ½µÄ³èÎï, Ôò¸Ã³èÎïѧϰ¼¼ÄÜ  | 
|         fightPet = curPlayer.GetPetMgr().GetFightPet()  | 
|         if learnSkillList and fightPet:  | 
|             PetControl.DoLogic_PlayerPetLearnSkillList(fightPet, learnSkillList)  | 
|               | 
|         RefreshPetItemAddAttr(curPlayer, True)  | 
|           | 
|         # ¿ª·þ»î¶¯Êý¾Ý  | 
|         OpenServerCampaign.UpdOpenServerCampaignRecordData(curPlayer, ShareDefine.Def_Campaign_Type_PetLV, GetTotalPetLV(curPlayer))  | 
|           | 
|     PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_PetClassLV, 1, [petNPCID, updClassLV + 1])  | 
|     extraInfoDict = {"petItemIndex":PetItemIndex, "petNPCID":petNPCID}  | 
|     extraInfoDict.update(eval(petDataItem.GetUserData()))  | 
|     DataRecordPack.DR_ClassUpSystem(curPlayer, "PetClassUp", updClassLV, extraInfoDict)  | 
|           | 
|     #EventReport.WriteEvent_pet_class(curPlayer, petNpcData.GetName(), classLV, petClassExp, updClassLV, newClassExp)  | 
|       | 
|     PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {autoBuyItemID:costItemCount})  | 
|     PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetUpItem, costItemCount)  | 
|     return  | 
|   | 
| def __UpdPetItemSkillByClass(curPlayer, petDataItem, isNotify=False):  | 
|     # Éý½×¸üÐÂÁé³è¼¼ÄÜ£¬Ö§³ÖͬskillTypeID¼¼ÄÜÉý¼¶  | 
|     playerName = curPlayer.GetName()  | 
|     petNPCID = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|     classLV = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV) + 1  | 
|     itemSkillList = []  | 
|     itemSkillCount = petDataItem.GetUserAttrCount(ShareDefine.Def_IudetPet_Skill)  | 
|     for i in xrange(itemSkillCount):  | 
|         skillID = petDataItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, i)  | 
|         skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|         if not skillData:  | 
|             continue  | 
|         skillTypeID = skillData.GetSkillTypeID()  | 
|         itemSkillList.append([skillTypeID, skillID])  | 
|     #GameWorld.DebugLog("¿ªÊ¼¸üÐÂÁé³è¼¼ÄÜ: petNPCID=%s,classLV=%s,itemSkillList=%s" % (petNPCID, classLV, itemSkillList))  | 
|       | 
|     petIpyData = GetPetIpydata(petNPCID)  | 
|     petSkillList = petIpyData.GetSkillID()  | 
|     petSkillUnLockList = petIpyData.GetSkillUnLock()  | 
|     sysMarkList = petIpyData.GetSkillUnLockSys()  | 
|     learnSkillList = []  | 
|     skillChange = False  | 
|     for i, skillID in enumerate(petSkillList):  | 
|         limitPetClassLV = petSkillUnLockList[i] # Ñ§Ï°´Ë¼¼ÄÜËùÐè³èÎï½×¼¶  | 
|         if classLV < limitPetClassLV:  | 
|             GameWorld.DebugLog("    Î´Âú×ãѧϰ½×¼¶: i=%s,skillID=%s,limitPetClassLV=%s" % (i, skillID, limitPetClassLV))  | 
|             break  | 
|         skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|         if not skillData:  | 
|             continue  | 
|         skillTypeID = skillData.GetSkillTypeID()  | 
|         alreadyLearnSkillID, alreadyLearnIndex = 0, -1  | 
|         for skillIndex, skillInfo in enumerate(itemSkillList):  | 
|             itemSkillTypeID, itemSkillID = skillInfo  | 
|             if itemSkillTypeID == skillTypeID:  | 
|                 alreadyLearnSkillID = itemSkillID  | 
|                 alreadyLearnIndex = skillIndex  | 
|                 break  | 
|         if skillID <= alreadyLearnSkillID:  | 
|             #GameWorld.DebugLog("    ¼¼ÄÜÒѾѧϰ¹ý: i=%s,skillID=%s <= alreadyLearnSkillID=%s" % (i, skillID, alreadyLearnSkillID))  | 
|             continue  | 
|         if skillData.GetFuncType() == ChConfig.Def_SkillFuncType_PetOwnerSkill:  | 
|             #GameWorld.DebugLog("    Ö÷ÈËѧϰ¼¼ÄÜ: i=%s,skillID=%s" % (i, skillID))  | 
|             SkillCommon.GivePlayerSkillByJobSkill(curPlayer, [skillID])  | 
|             continue  | 
|         skillChange = True  | 
|         if not alreadyLearnSkillID:  | 
|             itemSkillList.append([skillTypeID, skillID])  | 
|         else:  | 
|             itemSkillList[alreadyLearnIndex] = [skillTypeID, skillID]  | 
|         if not SkillCommon.isPassiveAttr(skillData):  | 
|             #±»¶¯¼¼Äܲ»Ñ§  | 
|             learnSkillList.append(skillID)  | 
|         #¹ã²¥  | 
|         sysMark = sysMarkList[i] if i < len(sysMarkList) else 'PetUpLv'  | 
|         if isNotify and sysMark:  | 
|             PlayerControl.WorldNotify(0, sysMark, [playerName, petNPCID, limitPetClassLV, skillID])  | 
|         #Ôö¼ÓÉý¼¶»îÔ¾µãЧ¹û  | 
|         PlayerActivity.AddActivityByLVOnLearnSkill(curPlayer, skillID)  | 
|           | 
|     if not skillChange:  | 
|         return learnSkillList  | 
|       | 
|     for skillIndex, skillInfo in enumerate(itemSkillList):  | 
|         skillID = skillInfo[1]  | 
|         if skillIndex < itemSkillCount:  | 
|             itemSkillID = petDataItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, skillIndex)  | 
|             if itemSkillID != skillID:  | 
|                 #GameWorld.DebugLog("    Ñ§Ï°Éý¼¶¼¼ÄÜ: itemSkillID=%s -> skillID=%s,skillIndex=%s" % (itemSkillID, skillID, skillIndex))  | 
|                 petDataItem.UpdataUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, skillIndex, skillID)  | 
|         else:  | 
|             #GameWorld.DebugLog("    Ñ§Ï°Ðµļ¼ÄÜ: skillID=%s,skillIndex=%s" % (skillID, skillIndex))  | 
|             petDataItem.AddUserAttr(ShareDefine.Def_IudetPet_Skill, skillID)  | 
|               | 
|     nowSkillIDList = []  | 
|     for i in xrange(petDataItem.GetUserAttrCount(ShareDefine.Def_IudetPet_Skill)):  | 
|         nowSkillIDList.append(petDataItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, i))  | 
|     GameWorld.DebugLog("Áé³è×îм¼ÄÜ: nowSkillIDList=%s" % nowSkillIDList)  | 
|     return learnSkillList  | 
|   | 
| def GetTotalPetLV(curPlayer):  | 
|     totalPetLV = 0  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         petItem = petPack.GetAt(i)  | 
|         if petItem.IsEmpty():  | 
|             continue   | 
|         petItemNPCID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         classLV = petItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV) + 1  | 
|         petIpyData = GetPetIpydata(petItemNPCID)  | 
|         if not petIpyData:  | 
|             continue  | 
|         totalPetLV += classLV  | 
|     return totalPetLV  | 
|   | 
| def GetTotalPetCount(curPlayer):  | 
|     totalPetCount = 0  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         petItem = petPack.GetAt(i)  | 
|         if petItem.IsEmpty():  | 
|             continue   | 
|         petItemNPCID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         petIpyData = GetPetIpydata(petItemNPCID)  | 
|         if not petIpyData:  | 
|             continue  | 
|         totalPetCount += 1  | 
|     return totalPetCount  | 
|   | 
| ## Ë¢Ð³èÎïÊý¾ÝÎïÆ·Ôö¼ÓµÄÊôÐÔ  | 
| def RefreshPetItemAddAttr(curPlayer, isUpdBillboard):  | 
|     CalcPetItemAddPlayerAttr(curPlayer)  | 
|       | 
|     if isUpdBillboard:  | 
|         PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState(billboardFunc=PlayerBillboard.UpdatePyPetBillboard, isForce=True)  | 
|         #PlayerBillboard.UpdatePyPetBillboard(curPlayer, True)  | 
|     else:  | 
|         PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState(isForce=True)  | 
|           | 
|     #fightPet = curPlayer.GetPetMgr().GetFightPet()  | 
|     #if fightPet:  | 
|     #    PetControl.RefurbishPetAttr(fightPet)  | 
|     return  | 
|   | 
| def CalcSkill_PetBattleEffect(curPlayer, rolePet, allAttrListPet):  | 
|     #ÁéÊÞ¼¼ÄܸøÁéÊÞ¼ÓµÄÊôÐÔ£¬²»¸øÈËÎï¼ÓµÄÊôÐÔ  | 
|     learnSkillList, passiveSkillList = GetPetLearnSkill(curPlayer)  | 
|     #GameWorld.DebugLog("1Ë¢¼¼ÄÜÊôÐÔ: %s" % allAttrList)  | 
|     for skillID in passiveSkillList:  | 
|         curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|         if not curSkill:  | 
|             continue  | 
|         for effectIndex in xrange(curSkill.GetEffectCount()):  | 
|             curEffect = curSkill.GetEffect(effectIndex)  | 
|             if curEffect.GetEffectID() not in ChConfig.Def_SkillEffs_Pet:  | 
|                 # ²»¸ø³èÎï¼ÓµÄ²»´¦Àí  | 
|                 continue  | 
|             SkillShell.CalcBuffEffAttr(rolePet, curEffect, allAttrListPet)  | 
|   | 
|   | 
| ##¼ÆËãNPCÕ½¶·ÊôÐÔ  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ¼ÆËãNPCÕ½¶·ÊôÐÔ  | 
| def CalcBuffer_PetBattleEffect(rolePet, allAttrListPet):  | 
|     #@warning:Õ½¶·ÊôÐÔÏÈËã·ÇÏßÐÔÔÚËãÏßÐÔ  | 
|     buffRefreshList = NPCCommon.GetNPCBuffRefreshList(rolePet)  | 
|       | 
|     for buffState, canPileup in buffRefreshList:  | 
|         SkillShell.CalcCurBuffer_Effect(buffState, rolePet, allAttrListPet)  | 
|       | 
|     #·ÇÏßÐÔ  | 
|     CalcNoLineEffect.ChangeNPCAttrInNoLineEffectList(rolePet, allAttrListPet[ChConfig.CalcAttr_BattleNoline])  | 
|     #ÏßÐÔ  | 
|     CalcLineEffect.ChangeNPCAttrInLineEffectList(rolePet, allAttrListPet[ChConfig.CalcAttr_Battle])  | 
|     return  | 
|   | 
|   | 
| ## ¼ÆËã³èÎïÔö¼ÓµÄÍæ¼ÒÊôÐÔ  | 
| #  @param curPlayer Íæ¼Ò  | 
| #  @return None  | 
| def CalcPetItemAddPlayerAttr(curPlayer):  | 
|     allAttrListPet = [{} for _ in range(4)]  | 
|     allAttrListPetSign = [{} for _ in range(4)] # ÊôÐÔº¬ ÌØÊâµÄ¼¼ÄÜÊôÐÔ(ÒòΪǩµ½¼¼ÄÜÊôÐԳɳ¤£¬Õ½Á¦Ò²Êdzɳ¤µÄ£¬ËùÒÔ²»Äܷż¼ÄÜÖÐËãÕ½Á¦£¬ÔÝʱ·Å»êʯÖÐ)  | 
|     allAttrListPetSoul = [{} for _ in range(4)]  | 
|     skillAttrList = [{} for _ in range(4)]  | 
|     allAttrListPetSkin = [{} for _ in range(4)]  | 
|     allAttrListTrain = [{} for _ in range(4)]  | 
|     allAttrListStar = [{} for _ in range(4)]  | 
|     customAttrDictPet = {}  | 
|     totalMinAtk, totalMaxAtk, qualityAttrInfo = GetPetAtkValue(curPlayer)  | 
|     customAttrDictPet["petQualityAttrInfo"] = qualityAttrInfo  | 
|     PlayerControl.CalcAttrDict_Type(ShareDefine.Def_Effect_PetMinAtk, totalMinAtk, allAttrListPet)  | 
|     PlayerControl.CalcAttrDict_Type(ShareDefine.Def_Effect_PetMaxAtk, totalMaxAtk, allAttrListPet)  | 
|     totalSignNum = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TotalSignNum) # ×ÜÇ©µ½ÌìÊý  | 
|     # ¹ûʵ¸øÈËÎï¼ÓÊôÐÔ, »êʯ¹ûʵË㸽¼ÓÊôÐԲ㣬µ¥¶À¼ÆËã  | 
|     fightPowerEx = PlayerAttrFruit.CalcAttrFruitAddAtrr(curPlayer, allAttrListPetSoul, ShareDefine.Def_AttrFruitFunc_Pet)  | 
|     curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % ShareDefine.Def_MFPType_PetSoul, fightPowerEx)  | 
|       | 
|     #ÁéÊÞ¼¼ÄܸøÈËÎï¼ÓµÄÊôÐÔ  | 
|     learnSkillList, passiveSkillList = GetPetLearnSkill(curPlayer)  | 
|     #GameWorld.DebugLog("1Ë¢¼¼ÄÜÊôÐÔ: %s" % allAttrList)  | 
|     for skillID in passiveSkillList:  | 
|         curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|         if not curSkill:  | 
|             continue  | 
|         # Áé³èÇ©µ½¼¼ÄÜÌØÊâ´¦Àí  | 
|         if curSkill.GetSkillTypeID() == ChConfig.Def_SkillID_PetSignDay:  | 
|             for effectIndex in xrange(curSkill.GetEffectCount()):  | 
|                 curEffect = curSkill.GetEffect(effectIndex)  | 
|                 effID = curEffect.GetEffectID()  | 
|                 effValue = curEffect.GetEffectValue(0)  | 
|                 PlayerControl.CalcAttrDict_Type(effID, effValue * totalSignNum, allAttrListPetSign)  | 
|               | 
|             continue  | 
|         for effectIndex in xrange(curSkill.GetEffectCount()):  | 
|             curEffect = curSkill.GetEffect(effectIndex)  | 
|             if curEffect.GetEffectID() in ChConfig.Def_SkillEffs_Pet:  | 
|                 # ¸ø³èÎï¼ÓµÄ²»´¦Àí  | 
|                 continue  | 
|             SkillShell.CalcBuffEffAttr(curPlayer, curEffect, skillAttrList)  | 
|       | 
|     # ÐÂÅàÑøÊôÐÔ  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in xrange(ipyDataMgr.GetPetTrainCount()):  | 
|         trainIpyData = ipyDataMgr.GetPetTrainByIndex(index)  | 
|         trainType = trainIpyData.GetTrainType()  | 
|         dataTrainLV = trainIpyData.GetTrainLV()  | 
|         trainLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainLV % trainType)  | 
|           | 
|         if dataTrainLV > trainLV:  | 
|             continue  | 
|         elif dataTrainLV == trainLV:  | 
|             trainItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainItemCount % trainType)  | 
|         else:  | 
|             trainItemCount = trainIpyData.GetEatCntTotal()  | 
|               | 
|         # µÈ½×¶îÍâÊôÐÔ  | 
|         lvAttrTypeList = trainIpyData.GetLVAttrTypeList()  | 
|         lvAttrValueList = trainIpyData.GetLVAttrValueList()  | 
|         for i, attrID in enumerate(lvAttrTypeList):  | 
|             attrValue = lvAttrValueList[i]  | 
|             PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListTrain)  | 
|               | 
|         # ÅàÑøµ¤Ôö¼ÓÊôÐÔ  | 
|         eatCntEverytime = trainIpyData.GetEatCntEverytime()  | 
|         if trainItemCount and eatCntEverytime:  | 
|             eatItemAttrTypeList = trainIpyData.GetEatItemAttrTypeList()  | 
|             eatItemAttrValueList = trainIpyData.GetEatItemAttrValueList()  | 
|             attrMultiple = trainItemCount / eatCntEverytime  | 
|             for i, attrID in enumerate(eatItemAttrTypeList):  | 
|                 attrValue = eatItemAttrValueList[i]  | 
|                 PlayerControl.CalcAttrDict_Type(attrID, attrValue * attrMultiple, allAttrListTrain)  | 
|                   | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetTarin, allAttrListTrain)  | 
|       | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Pet, allAttrListPet, customAttrDict=customAttrDictPet)  | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetSoul, allAttrListPetSoul)  | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetSign, allAttrListPetSign)  | 
|       | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetSkill, skillAttrList)  | 
|       | 
|     #³õʼսÁ¦  | 
|     fpExTotal = 0  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         petItem = petPack.GetAt(i)  | 
|         if petItem.IsEmpty():  | 
|             continue  | 
|         # ÎïÆ·Éϵļ¼ÄÜÕ½Á¦£¬Ö÷ÈËÉϵÄÁíËã  | 
|         for i in range(petItem.GetUserAttrCount(ShareDefine.Def_IudetPet_Skill)):  | 
|             skillID = petItem.GetUserAttrByIndex(ShareDefine.Def_IudetPet_Skill, i)  | 
|             curSkilData = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|             if not curSkilData:  | 
|                 continue  | 
|             fpExTotal += curSkilData.GetFightPower()  | 
|         petItemNPCID = petItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         petIpyData = GetPetIpydata(petItemNPCID)  | 
|         if not petIpyData:  | 
|             continue  | 
|         fpExTotal += petIpyData.GetInitFightPower() # ³õʼսÁ¦  | 
|         #¾õÐÑÕ½Á¦  | 
|         skinData = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HorsePetSkinData % (2, petItemNPCID), 0)  | 
|         skinIpyData = IpyGameDataPY.GetIpyGameDataNotLog('HorsePetSkin', 2, petItemNPCID, skinData / 100)  | 
|         if skinIpyData:  | 
|             for attrID, attrValue in skinIpyData.GetAttrInfo().items():  | 
|                 PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListPetSkin)  | 
|                   | 
|         #ÐǼ¶  | 
|         curStar = petItem.GetUserAttr(ShareDefine.Def_IudetPet_Star)  | 
|         starIpyData = IpyGameDataPY.GetIpyGameDataNotLog("PetStarUp", petItemNPCID, curStar)  | 
|         if starIpyData:  | 
|             starAttrType = starIpyData.GetStarAttrType()  | 
|             starAttrValue = starIpyData.GetStarAttrValue()  | 
|             for i, attrID in enumerate(starAttrType):  | 
|                 attrValue = starAttrValue[i]  | 
|                 PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListStar)  | 
|                   | 
|         #Éý½×  | 
|         classlv = petItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV) + 1  | 
|         classIpyData = IpyGameDataPY.GetIpyGameDataNotLog("PetClassCost", petItemNPCID, classlv)  | 
|         if classIpyData:  | 
|             attrTypeList = classIpyData.GetAttrType()  | 
|             attrValueList = classIpyData.GetAttrValue()  | 
|             for i, attrID in enumerate(attrTypeList):  | 
|                 attrValue = attrValueList[i]  | 
|                 PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListStar)  | 
|                   | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetSkin, allAttrListPetSkin)  | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_PetStar, allAttrListStar)  | 
|     curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % ShareDefine.Def_MFPType_Pet, fpExTotal)  | 
| #    GameWorld.DebugLog("³èÎï°ñNPCID: %s, petDict=%s" % (billPetNPCID, str(billPetDict)))  | 
|     return  | 
|   | 
| ## »ñÈ¡ÁéÊÞ³öսʱµÄ¹¥»÷Á¦  | 
| def GetPetAtkValue(curPlayer):  | 
|     qualityAttrInfo = {}  | 
|     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Pet):  | 
|         #GameWorld.DebugLog(' ³èÎ﹦ÄÜ먦Æô')  | 
|         return 0, 0, qualityAttrInfo  | 
|       | 
|     classAddAtk = 0  | 
|     petPackIndex = ShareDefine.rptPet  | 
|     petPack = curPlayer.GetItemManager().GetPack(petPackIndex)  | 
|     for i in range(petPack.GetCount()):  | 
|         packItem = petPack.GetAt(i)  | 
|         if packItem.IsEmpty():  | 
|             continue  | 
|         petItemNPCID = packItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|         classlv = packItem.GetUserAttr(ShareDefine.Def_IudetPet_ClassLV)  | 
|         classIpyData = IpyGameDataPY.GetIpyGameData("PetClassCost", petItemNPCID, classlv + 1)  | 
|         atkAdd = classIpyData.GetAtkAdd() if classIpyData else 0  | 
|         classAddAtk += atkAdd  | 
|           | 
|         petIpyData = GetPetIpydata(petItemNPCID)  | 
|         if petIpyData:  | 
|             quality = petIpyData.GetQuality()  | 
|             if quality not in qualityAttrInfo:  | 
|                 qualityAttrInfo[quality] = {}  | 
|             qualityAttrDict = qualityAttrInfo[quality]  | 
|             qualityAttrDict[ShareDefine.Def_Effect_PetAtk] = qualityAttrDict.get(ShareDefine.Def_Effect_PetAtk, 0) + atkAdd  | 
|               | 
|     totalMinAtk = classAddAtk  | 
|     totalMaxAtk = classAddAtk  | 
|     return totalMinAtk, totalMaxAtk, qualityAttrInfo  | 
|   | 
| def GetPetTrainTypes():  | 
|     return len(IpyGameDataPY.GetFuncEvalCfg("PetUpItem", 3))  | 
|   | 
| #// A7 05 ³èÎïÅàÑø #tagCMPetTrain  | 
| #  | 
| #struct    tagCMPetTrain  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        TrainType;        //ÅàÑøÀàÐÍ£º 1-»ù´¡ÅàÑø£¬2-ÌØÊâÅàÑø£¬3-°Ù·Ö±ÈÅàÑø  | 
| #    WORD        UseItemCnt;        //ÏûºÄ²ÄÁϸöÊý  | 
| #};  | 
| def OnPetTrain(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     trainType = clientData.TrainType # ÅàÑøÀàÐÍ  | 
|     costItemCount = clientData.UseItemCnt # ÏûºÄ²ÄÁϸöÊý  | 
|       | 
|     trainLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainLV % trainType)  | 
|     curEatItemCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainItemCount % trainType)  | 
|     GameWorld.DebugLog("Áé³èÅàÑø: trainType=%s,trainLV=%s,costItemCount=%s,curEatItemCount=%s"   | 
|                        % (trainType, trainLV, costItemCount, curEatItemCount))  | 
|       | 
|     if trainType <= 0 or trainType > GetPetTrainTypes():  | 
|         return  | 
|       | 
|     if trainLV <= 0:  | 
|         GameWorld.DebugLog("    ÅàÑøÎ´¼¤»î  trainType=%s" % trainType)  | 
|         return  | 
|       | 
|     trainIpyData = IpyGameDataPY.GetIpyGameData("PetTrain", trainType, trainLV)  | 
|     if not trainIpyData:  | 
|         return  | 
|       | 
|     needRealmLV = trainIpyData.GetNeedRealmLV()  | 
|     curRealmLV = PlayerControl.GetTrainRealmLVReal(curPlayer, 2)  | 
|     if curRealmLV < needRealmLV:  | 
|         GameWorld.DebugLog("    ¾³½ç²»×㣬ÎÞ·¨ÅàÑø£¡  curRealmLV(%s) < needRealmLV(%s)" % (curRealmLV, needRealmLV))  | 
|         return  | 
|       | 
|     needEatCountTotal = trainIpyData.GetEatCntTotal()  | 
|     if not needEatCountTotal:  | 
|         GameWorld.DebugLog("    ¸ÃÅàÑøÒÑÂú¼¶£¡")  | 
|         return  | 
|       | 
|     costItemIDList = IpyGameDataPY.GetFuncEvalCfg("PetUpItem", 3)  | 
|     costItemID = costItemIDList[trainType - 1]  | 
|     if not costItemID or not costItemCount:  | 
|         return  | 
|       | 
|     costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, costItemCount)  | 
|     lackCnt = costItemCount - bindCnt - unBindCnt  | 
|     if lackCnt > 0:  | 
|         GameWorld.DebugLog("    ÏûºÄµÀ¾ß²»×㣬ÎÞ·¨ÅàÑø!costItemID=%s,costItemCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"   | 
|                            % (costItemID, costItemCount, bindCnt, unBindCnt, lackCnt))  | 
|         return  | 
|       | 
|     delCnt = costItemCount  | 
|       | 
|     # ¿Û³ýÏûºÄ  | 
|     if delCnt:  | 
|         ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, delCnt, ChConfig.ItemDel_Pet)  | 
|           | 
|     updClassLV = trainLV  | 
|     updEatItemCount = curEatItemCount + costItemCount  | 
|     GameWorld.DebugLog("    updEatItemCount=%s,needEatCountTotal=%s" % (updEatItemCount, needEatCountTotal))  | 
|       | 
|     if updEatItemCount >= needEatCountTotal:  | 
|         updClassLV += 1  | 
|         updEatItemCount -= needEatCountTotal  | 
|         GameWorld.DebugLog("    ½ø½×: updClassLV=%s,updEatItemCount=%s" % (updClassLV, updEatItemCount))  | 
|           | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PetTrainLV % trainType, updClassLV)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PetTrainItemCount % trainType, updEatItemCount)  | 
|       | 
|     # Éý½×  | 
|     if updClassLV > trainLV:  | 
|         pass  | 
|       | 
|     Sync_PetTrainData(curPlayer)  | 
|     # Ë¢ÊôÐÔ£¬¸üÐÂÅÅÐаñ  | 
|     RefreshPetItemAddAttr(curPlayer, True)  | 
|       | 
|     PlayerActHorsePetTrain.OnHorsePetTrainCost(curPlayer, {costItemID:costItemCount})  | 
|     if trainType == 2:  | 
|         PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetTrainItem2, costItemCount)  | 
|     elif trainType == 3:  | 
|         PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_PetTrainItem3, costItemCount)  | 
|     return  | 
|   | 
| #// A7 06 ³èÎïÉýÐÇ #tagCMPetStarUp  | 
| #  | 
| #struct    tagCMPetStarUp  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        PetItemIndex;    //³èÎïÊý¾Ý±³°üË÷Òý  | 
| #};  | 
| def OnPetStarUp(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     PetItemIndex = clientData.PetItemIndex  | 
|     petDataItem = GetPetDataItemByIndex(curPlayer, PetItemIndex)  | 
|     if not petDataItem:  | 
|         return  | 
|     petNPCID = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_NPCID)  | 
|     curStar = petDataItem.GetUserAttr(ShareDefine.Def_IudetPet_Star)  | 
|     nextStar = curStar + 1  | 
|     nextIpyData = IpyGameDataPY.GetIpyGameDataNotLog("PetStarUp", petNPCID, nextStar)  | 
|     if not nextIpyData:  | 
|         GameWorld.DebugLog("Áé³è²»´æÔÚ¸ÃÐǼ¶£¬ÎÞ·¨ÉýÐÇ. petNPCID=%s,curStar=%s" % (petNPCID, curStar), playerID)  | 
|         return  | 
|     needItemList = nextIpyData.GetStarUpNeedItemList()  | 
|     if not needItemList:  | 
|         return  | 
|     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)  | 
|     lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needItemList, itemPack)  | 
|     if lackItemDict:  | 
|         GameWorld.DebugLog("Áé³èÉýÐÇËùÐèÎïÆ·²»×㣡 petNPCID=%s,nextStar=%s,needItemList=%s,lackItemDict=%s"   | 
|                            % (petNPCID, nextStar, needItemList, lackItemDict), playerID)  | 
|         return  | 
|       | 
|     ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, "PetStarUp")      | 
|     petDataItem.SetUserAttr(ShareDefine.Def_IudetPet_Star, nextStar)  | 
|     GameWorld.DebugLog("Áé³èÉýÐÇ. petNPCID=%s,curStar=%s,nextStar=%s" % (petNPCID, curStar, nextStar), playerID)  | 
|       | 
|     RefreshPetItemAddAttr(curPlayer, True)      | 
|     return  | 
|   | 
| def Sync_PetTrainData(curPlayer):  | 
|     clientPack = ChPyNetSendPack.tagMCPetTrainInfo()  | 
|     clientPack.TrainLVList = []  | 
|     clientPack.TrainItemCountList = []  | 
|     for trainType in xrange(1, GetPetTrainTypes() + 1):  | 
|         clientPack.TrainLVList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainLV % trainType))  | 
|         clientPack.TrainItemCountList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PetTrainItemCount % trainType))  | 
|     clientPack.TrainTypes = len(clientPack.TrainLVList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  | 
|   |