New file |
| | |
| | | #!/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
|
| | |
|
| | |
|