| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package Player.PlayerChangeJob  | 
| #  | 
| # @todo:תְҵ  | 
| # @author hxp  | 
| # @date 2022-10-14  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ×ªÖ°Òµ  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2022-10-14 19:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import ShareDefine  | 
| import IpyGameDataPY  | 
| import IPY_GameWorld  | 
| import PlayerBillboard  | 
| import Item_ResetAttrPoint  | 
| import DataRecordPack  | 
| import PlayerControl  | 
| import ItemControler  | 
| import ItemCommon  | 
| import ChConfig  | 
|   | 
|   | 
| def DoChangeJob(curPlayer, curJob, tagJob, isFree=False):  | 
|     ''' ×ª»»Ö°Òµ£¬Îª·Àֹתְҵ¹ý³Ìʧ°Ü£¬¸Ãº¯Êý¿ÉÖØ¸´Ö´Ðе÷Óã¬Èç¹ûÍæ¼Òתְ³öÏÖÒì³££¬¿Éͨ¹ýºǫ́GMÖ±½ÓÖ´ÐÐÃüÁîÖØ¸´²Ù×÷תְ  | 
|     '''  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     GameWorld.Log("Íæ¼Òתְҵ: playerJob=%s,curJob=%s,tagJob=%s,isFree=%s"   | 
|                   % (curPlayer.GetJob(), curJob, tagJob, isFree), playerID)  | 
|     if curJob == tagJob:  | 
|         return  | 
|     jobList = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1)  | 
|     if curJob not in jobList or tagJob not in jobList:  | 
|         return  | 
|       | 
|     if not isFree:  | 
|         costItemInfo = IpyGameDataPY.GetFuncEvalCfg("ChangeJob", 1) # ËùÐèÎïÆ·ID|¸öÊý  | 
|         costItemID, costItemCount = costItemInfo  | 
|           | 
|         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), playerID)  | 
|             return  | 
|           | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|       | 
|     # 1.¼¼ÄÜ£¨ÈË×å·¨±¦¼¼ÄÜ£¬ÆÕ¹¥¼¼ÄÜ£¬Ô¦Áé¾í¼¼ÄÜ£¬·¹ö¼¼ÄÜ£¬¾³½ç¼¼ÄÜ£¬×¨¾«£©  | 
|     # ÎåÐÐר¾« Ö±½ÓÖØÖà  | 
|     delSkillIDList = [] # ÐèҪɾ³ýµÄ¼¼ÄÜIDÁÐ±í  | 
|     replaceSkillDict = {} # ÐèÒªÌæ»»µÄ¼¼ÄÜÐÅÏ¢ {skillID:Ìæ»»¼¼ÄÜID, ...}  | 
|     skillManager = curPlayer.GetSkillManager()  | 
|     for i in range(skillManager.GetSkillCount()):  | 
|         curSkill = skillManager.GetSkillByIndex(i)  | 
|         if not curSkill:  | 
|             continue  | 
|           | 
|         skillUseType = curSkill.GetUseType()  | 
|         if skillUseType == 0:  | 
|             # ÎÞÖ°ÒµÏÞÖÆ  | 
|             continue  | 
|         if not skillUseType & pow(2, curJob):  | 
|             continue  | 
|           | 
|         funcType = curSkill.GetFuncType()  | 
|         skillID = curSkill.GetSkillID()  | 
|         skillTypeID = curSkill.GetSkillTypeID()  | 
|         if funcType in [ChConfig.Def_SkillFuncType_FbSPSkill]:  | 
|             delSkillIDList.append(skillID)  | 
|         else:  | 
|             replaceSkillDict[skillTypeID] = [skillID, curSkill.GetSkillLV(), 0]  | 
|               | 
|     # 1.1 ÆÕ¹¥  | 
|     curJobCommAtkSkillIDList = IpyGameDataPY.GetFuncEvalCfg("JobFitterSkill", curJob)  | 
|     tagJobCommAtkSkillIDList = IpyGameDataPY.GetFuncEvalCfg("JobFitterSkill", tagJob)  | 
|     if len(curJobCommAtkSkillIDList) != len(tagJobCommAtkSkillIDList):  | 
|         GameWorld.ErrLog("תְҵÆÕ¹¥¶ÔÓ¦¼¼ÄÜÅäÖôíÎó! curJob=%s,tagJob=%s" % (curJob, tagJob), playerID)  | 
|         return  | 
|     for i, skillTypeID in enumerate(curJobCommAtkSkillIDList):  | 
|         if skillTypeID in replaceSkillDict:  | 
|             replaceSkillDict[skillTypeID][-1] = tagJobCommAtkSkillIDList[i]  | 
|               | 
|     # 1.2 ·¨±¦ - Ö÷¶¯¼¼ÄÜ  | 
|     for index in range(ipyDataMgr.GetTreasureUpCount()):  | 
|         ipyData = ipyDataMgr.GetTreasureUpByIndex(index)  | 
|         UnLockSkillList = ipyData.GetUnLockSkill()  | 
|         for skillTypeID in UnLockSkillList:  | 
|             if skillTypeID not in replaceSkillDict:  | 
|                 continue  | 
|             if tagJob > len(UnLockSkillList):  | 
|                 GameWorld.ErrLog("·¨±¦Éý¼¶±íδÅäÖÃתְҵ¶ÔÓ¦¼¼ÄÜ! skillTypeID=%s,tagJob=%s" % (skillTypeID, tagJob), playerID)  | 
|                 return  | 
|             replaceSkillDict[skillTypeID][-1] = UnLockSkillList[tagJob - 1]  | 
|             break  | 
|           | 
|     # 1.3 ¾³½ç - ±»¶¯¼¼ÄÜ  | 
|     for index in range(ipyDataMgr.GetRealmCount()):  | 
|         ipyData = ipyDataMgr.GetRealmByIndex(index)  | 
|         LearnSkillIDInfo = ipyData.GetLearnSkillIDInfo()  | 
|         if str(curJob) not in LearnSkillIDInfo:  | 
|             continue  | 
|         curJobLearnSkillIDList = LearnSkillIDInfo[str(curJob)]  | 
|         tagJobLearnSkillIDList = LearnSkillIDInfo.get(str(tagJob), [])  | 
|         for i, skillTypeID in enumerate(curJobLearnSkillIDList):  | 
|             if skillTypeID not in replaceSkillDict:  | 
|                 continue  | 
|             if i >= len(tagJobLearnSkillIDList):  | 
|                 GameWorld.ErrLog("¾³½ç±íδÅäÖÃתְҵ¶ÔÓ¦¼¼ÄÜ! skillTypeID=%s,tagJob=%s" % (skillTypeID, tagJob), playerID)  | 
|                 return  | 
|             replaceSkillDict[skillTypeID][-1] = tagJobLearnSkillIDList[i]  | 
|             break  | 
|           | 
|     for skillTypeID, repInfo in replaceSkillDict.items():  | 
|         skillID, skillLV, repSkillTypeID = repInfo  | 
|         if not repSkillTypeID or not GameWorld.GetGameData().GetSkillBySkillID(repSkillTypeID):  | 
|             GameWorld.ErrLog("Íæ¼ÒתְҵʱÕÒ²»µ½¿ÉÌæ»»µÄÄ¿±êÖ°Òµ¼¼ÄÜÊý¾Ý! skillTypeID=%s,skillID=%s,skillLV=%s,repSkillTypeID=%s,tagJob=%s"   | 
|                              % (skillTypeID, skillID, skillLV, repSkillTypeID, tagJob), playerID)  | 
|             return  | 
|           | 
|     # 2. ÎïÆ·£º Ö°Òµ×°±¸¡¢³á°ò¡¢Ê±×°  | 
|     itemColorMin = IpyGameDataPY.GetFuncCfg("ChangeJob", 2) # ±³°üÖÐÐèҪת»»µÄ×îµÍ×°±¸ÑÕɫƷÖÊ  | 
|     auctionItemNeed = IpyGameDataPY.GetFuncCfg("ChangeJob", 3) # ±³°üÖÐÅÄÆ·ÊÇ·ñת»»  | 
|     jobWingIDListInfo = IpyGameDataPY.GetFuncEvalCfg("ChangeJob", 4, {}) # Ö°Òµ¶ÔÓ¦³á°òIDÍ»ÆÆË³ÐòÁбí {Ö°Òµ:[³á°òÎïÆ·ID, ...], ...}  | 
|     costItemIDList = [] # Ê±×°×°±¸ÎïÆ·ID×éÁбí [[Ö°Òµ1ʱװID, Ö°Òµ2ʱװID, ...], ...]  | 
|     for index in range(ipyDataMgr.GetCoatCount()):  | 
|         ipyData = ipyDataMgr.GetCoatByIndex(index)  | 
|         costItemIDList.append(ipyData.GetEquipItemID())  | 
|           | 
|     replaceItemList = []  | 
|     for packType in [IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse, IPY_GameWorld.rptEquip]:  | 
|         equipPack = curPlayer.GetItemManager().GetPack(packType)  | 
|         for index in range(equipPack.GetCount()):  | 
|             curItem = equipPack.GetAt(index)  | 
|             if not curItem or curItem.IsEmpty():  | 
|                 continue  | 
|               | 
|             itemID = curItem.GetItemTypeID()  | 
|             itemPlace = curItem.GetEquipPlace()  | 
|             itemColor = curItem.GetItemColor()  | 
|               | 
|             # ±³°ü¡¢²Ö¿â ¶îÍâÌõ¼þ  | 
|             if packType in [IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse]:  | 
|                 if ItemCommon.CheckItemIsEquip(curItem) and itemPlace != ShareDefine.retWing:  | 
|                     if itemColor < itemColorMin:  | 
|                         continue  | 
|                     if not auctionItemNeed and ItemControler.GetIsAuctionItem(curItem):  | 
|                         continue  | 
|                       | 
|             itemJobLimit = curItem.GetJobLimit()  | 
|             if not itemJobLimit:  | 
|                 continue  | 
|               | 
|             if itemJobLimit != curJob:  | 
|                 # ·ÇÐèҪת»»µÄÖ°ÒµÎïÆ·²»´¦Àí  | 
|                 continue  | 
|               | 
|             # »ù´¡²¿Î», Ö±½Ó°´×°±¸ÎïÆ·IDÊ×λΪ¶ÔÓ¦Ö°Òµ½øÐÐÌæ»»  | 
|             if itemPlace in ChConfig.EquipPlace_Base:  | 
|                 tagJobItemID = GameWorld.ToIntDef("%s%s" % (tagJob, str(itemID)[1:]))  | 
|                 replaceItemList.append([packType, curItem, tagJobItemID])  | 
|                   | 
|             # Ê±×°  | 
|             elif itemPlace in [ShareDefine.retWeaponSkin, ShareDefine.retClothesSkin, ShareDefine.retWeapon2Skin]:  | 
|                 tagJobItemID = 0  | 
|                 for costJobItemIDList in costItemIDList:  | 
|                     if itemID not in costJobItemIDList:  | 
|                         continue  | 
|                     if tagJob > len(costJobItemIDList):  | 
|                         GameWorld.ErrLog("ʱװ±íδÅäÖÃתְҵ¶ÔӦʱװ! itemID=%s,tagJob=%s" % (itemID, tagJob), playerID)  | 
|                         return  | 
|                     tagJobItemID = costJobItemIDList[tagJob - 1]  | 
|                     break  | 
|                 replaceItemList.append([packType, curItem, tagJobItemID])  | 
|                   | 
|             # ³á°ò  | 
|             elif itemPlace == ShareDefine.retWing:  | 
|                 curJobWingIDList = jobWingIDListInfo.get(curJob, [])  | 
|                 tagJobWingIDList = jobWingIDListInfo.get(tagJob, [])  | 
|                 if len(curJobWingIDList) != len(tagJobWingIDList):  | 
|                     GameWorld.ErrLog("¹¦ÄÜÅäÖñíתְҵ¶ÔÓ¦³á°òID³¤¶ÈÅäÖò»Ò»ÖÂ! curJob=%s,tagJob=%s" % (curJob, tagJob), playerID)  | 
|                     return  | 
|                 if itemID in curJobWingIDList:  | 
|                     tagJobItemID = tagJobWingIDList[curJobWingIDList.index(itemID)]  | 
|                     replaceItemList.append([packType, curItem, tagJobItemID])  | 
|                       | 
|             else:  | 
|                 GameWorld.ErrLog("תְҵδ֪ת»»Âß¼µÄÎïÆ·ID! itemID=%s,tagJob=%s" % (itemID, tagJob), playerID)  | 
|                   | 
|     assignItemList = []  | 
|     for packType, curItem, tagJobItemID in replaceItemList:  | 
|         tagItem = ItemControler.GetOutPutItemObj(tagJobItemID, curItem.GetCount(), curPlayer=curPlayer)  | 
|         if not tagItem:  | 
|             GameWorld.ErrLog("תְҵʱ´´½¨ÎïÆ·Òì³£! tagJobItemID=%s,tagJob=%s" % (tagJobItemID, tagJob), playerID)  | 
|             return  | 
|         assignItemList.append([packType, curItem, tagItem])  | 
|           | 
|     ## -------- ÒÔÉÏΪÑéÖ¤¶¼Ã»ÓÐÈκÎÎÊÌâºó£¬¿ªÊ¼Ö´ÐÐ×ªÖ°ÒµÌæ»» ----------  | 
|     DR_ChangeJob(curPlayer, {"curJob":curJob, "tagJob":tagJob})  | 
|     delSkillIDList.sort()  | 
|     DR_ChangeJob(curPlayer, {"delSkillIDList":delSkillIDList, "replaceSkillDict":replaceSkillDict, "assignItemCount":len(assignItemList)})  | 
|     # ´¦Àí¼¼ÄÜ  | 
|     GameWorld.Log("ɾ³ý¼¼ÄÜ: ¸öÊý=%s,delSkillIDList=%s" % (len(delSkillIDList), delSkillIDList), playerID)  | 
|     for num, delSkillID in enumerate(delSkillIDList, 1):  | 
|         skillData = GameWorld.GetGameData().GetSkillBySkillID(delSkillID)  | 
|         skillName = skillData.GetSkillName() if skillData else ""  | 
|         skillManager.DeleteSkillBySkillID(delSkillID, False)  | 
|         GameWorld.Log("    É¾³ý¼¼ÄÜ %s: delSkillID=%s(%s)" % (num, delSkillID, skillName), playerID)  | 
|         DR_ChangeJob(curPlayer, {"delSkillID":delSkillID, "skillName":skillName})  | 
|           | 
|     repSkillTypeIDList = replaceSkillDict.keys()  | 
|     repSkillTypeIDList.sort()  | 
|     GameWorld.Log("Ìæ»»¼¼ÄÜ: ¸öÊý=%s,repSkillTypeIDList=%s" % (len(repSkillTypeIDList), repSkillTypeIDList), playerID)  | 
|     for num, skillTypeID in enumerate(repSkillTypeIDList, 1):  | 
|         skillID, skillLV, repSkillTypeID = replaceSkillDict[skillTypeID]  | 
|         skillManager.DeleteSkillBySkillID(skillID, False)  | 
|         for _ in range(skillLV):  | 
|             skillManager.LVUpSkillBySkillTypeID(repSkillTypeID)  | 
|         repSkill = skillManager.FindSkillBySkillTypeID(repSkillTypeID)  | 
|         repSkillID = repSkill.GetSkillID() if repSkill else 0  | 
|         skillData = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|         skillName = skillData.GetSkillName() if skillData else ""  | 
|         repSkillData = GameWorld.GetGameData().GetSkillBySkillID(repSkillID)  | 
|         repSkillName = repSkillData.GetSkillName() if repSkillData else ""  | 
|         GameWorld.Log("    Ìæ»»¼¼ÄÜ %s: skillTypeID=%s,skillID=%s(%s),skillLV=%s,tagJob=%s,repSkillTypeID=%s,repSkillID=%s(%s)"   | 
|                       % (num, skillTypeID, skillID, skillName, skillLV, tagJob, repSkillTypeID, repSkillID, repSkillName), playerID)  | 
|         DR_ChangeJob(curPlayer, {"skillTypeID":skillTypeID, "skillID":skillID, "skillLV":skillLV, "skillName":skillName,  | 
|                                  "repSkillTypeID":repSkillTypeID, "repSkillID":repSkillID, "repSkillName":repSkillName})  | 
|           | 
|     GameWorld.Log("ɾ³ýר¾«Ïà¹Ø×Öµä¼Ç¼Êý¾Ý", playerID)  | 
|     for index in range(ipyDataMgr.GetSkillElementCount()):  | 
|         ipyData = ipyDataMgr.GetSkillElementByIndex(index)  | 
|         elementSkillID = ipyData.GetElementSkillID()  | 
|         mainSkillID = ipyData.GetMainSkillID()  | 
|         selectElementSkillID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementID % mainSkillID)  | 
|         if selectElementSkillID:  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementID % mainSkillID, 0)  | 
|             mainSkillData = GameWorld.GetGameData().GetSkillBySkillID(mainSkillID)  | 
|             mainSkillName = mainSkillData.GetSkillName() if mainSkillData else ""  | 
|             selSkillData = GameWorld.GetGameData().GetSkillBySkillID(selectElementSkillID)  | 
|             selSkillName = selSkillData.GetSkillName() if selSkillData else ""  | 
|             GameWorld.Log("    È¡ÏûʹÓÃÖеÄר¾«: mainSkillID=%s(%s),selectElementSkillID=%s(%s)"   | 
|                           % (mainSkillID, mainSkillName, selectElementSkillID, selSkillName), playerID)  | 
|               | 
|         elementSkillIDLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementLV % elementSkillID)  | 
|         if elementSkillIDLV:  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementLV % elementSkillID, 0)              | 
|             elmSkillData = GameWorld.GetGameData().GetSkillBySkillID(elementSkillID)  | 
|             elmSkillName = elmSkillData.GetSkillName() if elmSkillData else ""  | 
|             GameWorld.Log("    ÖØÖÃר¾«¼Ç¼µÈ¼¶: elementSkillID=%s(%s),elementSkillIDLV=%s" % (elementSkillID, elmSkillName, elementSkillIDLV), playerID)  | 
|               | 
|     Item_ResetAttrPoint.DoResetAttrPoint(curPlayer, 0, 0)  | 
|       | 
|     # ´¦ÀíÎïÆ·  | 
|     GameWorld.Log("Ìæ»»ÎïÆ·: ¸öÊý=%s" % len(assignItemList), playerID)  | 
|     for num, itemInfo in enumerate(assignItemList, 1):  | 
|         packType, curItem, tagItem = itemInfo  | 
|         curItemID = curItem.GetItemTypeID()  | 
|         curItemName = curItem.GetName()  | 
|         curUserData = curItem.GetUserData()  | 
|         curAuctionItem = ItemControler.GetIsAuctionItem(curItem)  | 
|         curItemScore = ItemCommon.GetEquipGearScore(curItem)  | 
|           | 
|         tagItemID = tagItem.GetItemTypeID()  | 
|         tagItemName = tagItem.GetName()          | 
|         tagUserData = tagItem.GetUserData()  | 
|         tagAuctionItem = ItemControler.GetIsAuctionItem(tagItem)  | 
|           | 
|         if curAuctionItem != tagAuctionItem:  | 
|             ItemControler.SetIsAuctionItem(tagItem, curAuctionItem, curPlayer)  | 
|         tagItem.SetUserData(curUserData, len(curUserData)) # ¼Ì³ÐÎïÆ·×Ô¶¨ÒåÊý¾Ý  | 
|         ItemCommon.MakeEquipGS(tagItem)  | 
|         tagItemScore = ItemCommon.GetEquipGearScore(tagItem)  | 
|           | 
|         GameWorld.Log("    Ìæ»»ÎïÆ· %s: packType=%s,curItemID=%s(%s),curAuctionItem=%s,curItemScore=%s,tagJob=%s,tagItemID=%s(%s),tagItemScore=%s,curUserData=%s,tagUserData=%s"   | 
|                       % (num, packType, curItemID, curItemName, curAuctionItem, curItemScore, tagJob, tagItemID, tagItemName, tagItemScore, curUserData, tagUserData), playerID)  | 
|           | 
|         curItemDRDict = ItemCommon.GetItemNoteDict(curItem, curItem.GetCount())  | 
|         curItemDRDict.update({"ItemScore":curItemScore})  | 
|         tagItemDRDict = ItemCommon.GetItemNoteDict(tagItem, tagItem.GetCount())  | 
|         tagItemDRDict.update({"ItemScore":tagItemScore})  | 
|         DR_ChangeJob(curPlayer, {"packType":packType, "curItem":curItemDRDict, "tagItem":tagItemDRDict})  | 
|         curItem.AssignItem(tagItem)  | 
|           | 
|     # ¿Û³ýÏûºÄ  | 
|     if not isFree and costItemCount:  | 
|         ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, costItemCount, "ChangeJob")  | 
|           | 
|     curPlayer.SetJob(tagJob)  | 
|     GameWorld.Log("=== ×ªÖ°ÒµÍê±Ï: SetJob=%s ===" % tagJob, playerID)  | 
|     DR_ChangeJob(curPlayer, {"SetJob":tagJob})  | 
|       | 
|     PlayerControl.PlayerControl(curPlayer).ReCalcAllState()  | 
|     PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer, isAll=True)  | 
|       | 
|     # ÌßÏÂÏß  | 
|     curPlayer.Kick(IPY_GameWorld.disMapServerClose)  | 
|     return  | 
|   | 
| def DR_ChangeJob(curPlayer, dataDict):  | 
|     dataDict.update({"PlayerID":curPlayer.GetPlayerID(), "AccID":curPlayer.GetAccID()})  | 
|     DataRecordPack.SendEventPack("ChangeJob", dataDict, curPlayer)  | 
|     return  | 
|   | 
|   |