From 678aa6d401eaa1acc0b4f5ee3561e7d14b7b2aaf Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 14 十月 2022 19:01:10 +0800
Subject: [PATCH] 9731 【越南】【主干】【BT7】转职业

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py                       |   18 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChangeJob.py  |  289 ++++++++++++++++++++++++++++++++++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                     |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintSkill.py  |   41 ++++--
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py |    2 
 ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py                              |    2 
 6 files changed, 339 insertions(+), 19 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index f6ffb13..3a03d09 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -718,6 +718,8 @@
             PyGameData.g_todayPlayerLVDict[playerID] = packValue
 
     elif packType == IPY_GameServer.CDBPlayerRefresh_Job:
+        if packValue != curPlayer.GetJob():
+            PlayerBillboard.DelJobFightPowerBillboard(curPlayer, curPlayer.GetJob())
         curPlayer.SetJob(packValue)
         
 #    elif packType == IPY_GameServer.CDBPlayerRefresh_CurrentPlayerType:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
index 454063a..530252d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerBillboard.py
@@ -507,6 +507,21 @@
             
     return
 
+def DelJobFightPowerBillboard(curPlayer, delJob):
+    ## 删除玩家对应职业战力榜  - 一般是玩家职业改变了,需要删除旧职业的职业战力榜单
+    if delJob not in ShareDefine.JobFightPowerBillboardDict:
+        return
+    jobBType = ShareDefine.JobFightPowerBillboardDict[delJob]
+    playerID = curPlayer.GetPlayerID()
+    billboardMgr = GameWorld.GetBillboard()
+    playerBillBoard = billboardMgr.FindBillboard(jobBType)
+    if not playerBillBoard:
+        return
+    if playerBillBoard.FindByID(playerID):
+        playerBillBoard.DeleteByID(playerID)
+        GameWorld.DebugLog("删除玩家职业战力榜单: delJob=%s,jobBType=%s" % (delJob, jobBType), playerID)
+    return
+
 def GetBillboardOperateInfo(curPlayer):
     # 排行榜中所保存的运营商相关信息
     platform = curPlayer.GetAccID()
@@ -613,6 +628,9 @@
         if opInfo != str(curPlayerOpInfo):
             playerBillBoardData.SetName2(str(curPlayerOpInfo))
             GameWorld.DebugLog("    更新operatInfo=%s" % curPlayerOpInfo, curPlayerID)
+        if playerBillBoardData.GetType2() != billboardType:
+            playerBillBoardData.SetType2(billboardType)
+            GameWorld.DebugLog("    更新Type2=%s" % billboardType, curPlayerID)
         return False
     
     # 没设置值默认为时间time,先上榜的排前面
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index ecea2eb..4ae43d3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -414,7 +414,7 @@
 Writer = hxp
 Releaser = hxp
 RegType = 0
-RegisterPackCount = 23
+RegisterPackCount = 24
 
 PacketCMD_1 = 0xA5
 PacketSubCMD_1 = 0x04
@@ -508,6 +508,10 @@
 PacketSubCMD_23=0x35
 PacketCallFunc_23=OnSelectRealmDifficulty
 
+PacketCMD_24=0xA1
+PacketSubCMD_24=0x21
+PacketCallFunc_24=OnChangeJob
+
 ;购买相关的
 [BuySomething]
 ScriptName = Event\EventSrc\Operate_PlayerBuyZhenQi.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintSkill.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintSkill.py
index 64990b4..aa124dc 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintSkill.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintSkill.py
@@ -25,8 +25,10 @@
 #  @remarks 函数详细说明.
 def OnExec(curPlayer, cmdList):
     GameWorld.DebugAnswer(curPlayer, "----开始打印玩家技能, 带参数1输出被动技能")
+    GameWorld.DebugAnswer(curPlayer, "PrintSkill 是否显示技能名")
     skillDict = {}
     
+    showSkillName = cmdList[0] if len(cmdList) > 0 else 0
     skillManager = curPlayer.GetSkillManager()
     for i in range(0 , skillManager.GetSkillCount()):
         curSkill = skillManager.GetSkillByIndex(i)
@@ -35,10 +37,10 @@
         
         funcType = curSkill.GetFuncType()
         if funcType not in skillDict:
-            skillDict[funcType] = [curSkill.GetSkillID()]
-        else:
-            skillDict[funcType].append(curSkill.GetSkillID())
-    
+            skillDict[funcType] = {}
+        skillInfo = skillDict[funcType]
+        skillInfo[curSkill.GetSkillID()] = curSkill.GetSkillName()
+        
     showDict = {
                 0 : "随意",
                 1 : "人族法宝",
@@ -61,9 +63,14 @@
                 18 : "装备被动技能",
                 }
     
-    for funcType, skillList in skillDict.items():
-        GameWorld.DebugAnswer(curPlayer, "%s : %s"%(showDict.get(funcType, funcType), skillList))
-        
+    for funcType, skillInfo in skillDict.items():
+        skillIDList = skillInfo.keys()
+        skillIDList.sort()
+        GameWorld.DebugAnswer(curPlayer, "%s : %s" % (showDict.get(funcType, funcType), skillIDList))
+        if showSkillName:
+            for skillID in skillIDList:
+                GameWorld.DebugAnswer(curPlayer, "    %s : %s" % (skillID, skillInfo[skillID]))
+                
     ## 打印技能增减伤信息
     plusSkillTypeIDList = []
     skillPlusAttrIDDict = IpyGameDataPY.GetFuncEvalCfg("SkillPlusAttrID", 2, {})
@@ -83,31 +90,31 @@
     if not cmdList:
         return
     
-    passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(curPlayer )
+    passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(curPlayer)
     if not passiveEff:
         return
     
     GameWorld.DebugAnswer(curPlayer, "---------输出被动效果")
     
-    GameWorld.DebugAnswer(curPlayer, "被动效果 :%s"%passiveEff.AffectSkillDict)
+    GameWorld.DebugAnswer(curPlayer, "被动效果 :%s" % passiveEff.AffectSkillDict)
     
-    GameWorld.DebugAnswer(curPlayer, "选中的被动技能效果 :%s"%passiveEff.AffectPassiveSkillSetDict)
+    GameWorld.DebugAnswer(curPlayer, "选中的被动技能效果 :%s" % passiveEff.AffectPassiveSkillSetDict)
     
-    GameWorld.DebugAnswer(curPlayer, "被动BUFF效果 :%s"%passiveEff.AffectBuffDict)
+    GameWorld.DebugAnswer(curPlayer, "被动BUFF效果 :%s" % passiveEff.AffectBuffDict)
     
-    GameWorld.DebugAnswer(curPlayer, "神兽被动效果 :%s"%passiveEff.AffectDogzSkillDict)
+    GameWorld.DebugAnswer(curPlayer, "神兽被动效果 :%s" % passiveEff.AffectDogzSkillDict)
     
     
     
     fightPet = curPlayer.GetPetMgr().GetFightPet()
     if fightPet:
-        GameWorld.DebugAnswer(curPlayer, "出战宠物技能%s-%s"%PlayerPet.GetPetLearnSkill(curPlayer))
-        passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(fightPet )
+        GameWorld.DebugAnswer(curPlayer, "出战宠物技能%s-%s" % PlayerPet.GetPetLearnSkill(curPlayer))
+        passiveEff = PassiveBuffEffMng.GetPassiveEffManager().GetPassiveEff(fightPet)
         if not passiveEff:
             return
-        GameWorld.DebugAnswer(curPlayer, "宠物被动效果 :%s"%passiveEff.AffectSkillDict)
+        GameWorld.DebugAnswer(curPlayer, "宠物被动效果 :%s" % passiveEff.AffectSkillDict)
         
-        GameWorld.DebugAnswer(curPlayer, "宠物被动BUFF效果 :%s"%passiveEff.AffectBuffDict)
+        GameWorld.DebugAnswer(curPlayer, "宠物被动BUFF效果 :%s" % passiveEff.AffectBuffDict)
         
 #===============================================================================
 # (Def_SkillFuncType_Common, #0为通用技能
@@ -124,4 +131,4 @@
 # Def_SkillFuncType_RealmSuppress,  #11为境界压制 目前是NPC在用
 # Def_SkillFuncType_Dogz,     #12 神兽技能
 # Def_SkillFuncType_ZhuXian,     #13 诛仙技能
-#===============================================================================
\ No newline at end of file
+#===============================================================================
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
index 521fa71..a00c03b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
@@ -401,7 +401,7 @@
 
 def MakeEquipGS(curItem):
     if not CheckNoteEquipGS(curItem):
-        GameWorld.DebugLog("不设置装备评分")
+        #GameWorld.DebugLog("不设置装备评分")
         return
     value = CalcEquipGS(curItem)
     #GameWorld.DebugLog("设置装备评分: ItemID=%s,attrDict=%s,value=%s" % (curItem.GetItemTypeID(), attrDict, value))
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChangeJob.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChangeJob.py
new file mode 100644
index 0000000..3c8f709
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerChangeJob.py
@@ -0,0 +1,289 @@
+#!/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 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:
+                
+                # 无职业限制的需要处理翅膀
+                if 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])
+                        
+                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])
+                
+            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("替换物品: 个数=%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, ChConfig.ItemDel_EquipEnchant)
+        
+    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
+
+

--
Gitblit v1.8.0