| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package Player.PlayerGatherTheSoul  | 
| #  | 
| # @todo:¾Û»êР | 
| # @author hxp  | 
| # @date 2024-07-12  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ¾Û»êР | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2024-07-12 16:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import ShareDefine  | 
| import IpyGameDataPY  | 
| import ItemControler  | 
| import ChPyNetSendPack  | 
| import PassiveBuffEffMng  | 
| import PlayerSuccess  | 
| import PlayerControl  | 
| import NetPackCommon  | 
| import ChConfig  | 
|   | 
|   | 
| def OnPlayerLogin(curPlayer):  | 
|     if Sync_SoulInfo(curPlayer):  | 
|         Sync_SoulHoleInfo(curPlayer)  | 
|     return  | 
|   | 
| #// B2 25 Ð¾ۻê²Ù×÷ #tagCMGatherTheSoulOP  | 
| #  | 
| #struct    tagCMGatherTheSoulOP  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        OpType;    // 0-¼¤»îÉý¼¶; 1-´©´÷Ìæ»»; 2-жÏ  | 
| #    DWORD        SoulID;    // ¾Û»êID£»µ±²Ù×÷Éý¼¶Ê±£¬Èç¹ûΪ0´ú±íÒ»¼üÉý¼¶ËùÓпÉÉý¼¶µÄ  | 
| #};  | 
| def OnGatherTheSoulOP(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     OpType = clientData.OpType  | 
|     soulID = clientData.SoulID  | 
|     if OpType == 0:  | 
|         OnGatherTheSoulUp(curPlayer, soulID)  | 
|     elif OpType == 1:  | 
|         OnGatherTheSoulPuton(curPlayer, soulID)  | 
|     elif OpType == 2:  | 
|         OnGatherTheSoulTakeoff(curPlayer, soulID)  | 
|     elif OpType == 3:  | 
|         OnGatherTheSoulReset(curPlayer, soulID)  | 
|     return  | 
|   | 
| def OnGatherTheSoulUp(curPlayer, upSoulID):  | 
|     ## ¾Û»ê¼¤»îÉý¼¶  | 
|     # @param upSoulID: Ã»ÓÐÖ¸¶¨IDʱÔòÅúÁ¿´¦ÀíÉý¼¶  | 
|     if not upSoulID:  | 
|         soulIpyDataList = []  | 
|         ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|         for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|             soulIpyDataList.append(ipyDataMgr.GetGatherTheSoulByIndex(index))  | 
|     else:  | 
|         soulIpyDataList = [IpyGameDataPY.GetIpyGameData("GatherTheSoul", upSoulID)]  | 
|           | 
|     holeSoulChange = False  | 
|     updSoulIDList = []  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     for ipyData in soulIpyDataList:  | 
|         if not ipyData:  | 
|             continue  | 
|         soulID = ipyData.GetSoulID()  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         nextLV = soulLV + 1  | 
|         nextLVIpyData = IpyGameDataPY.GetIpyGameDataNotLog("GatherTheSoulLV", soulID, nextLV)  | 
|         if not nextLVIpyData:  | 
|             if soulLV:  | 
|                 GameWorld.DebugLog("¾Û»êÒÑÂú¼¶! soulID=%s,soulLV=%s" % (soulID, soulLV), playerID)  | 
|             continue  | 
|           | 
|         pieceItemID = ipyData.GetPieceItemID()  | 
|         holeNum = ipyData.GetHoleNum()  | 
|         needPieceCount = nextLVIpyData.GetNeedPiece()  | 
|         needSoulValue = nextLVIpyData.GetNeedSoulValue()  | 
|         playerPieceCount = ItemControler.GetItemCountByID(curPlayer, pieceItemID)  | 
|         if playerPieceCount < needPieceCount:  | 
|             GameWorld.DebugLog("¾Û»êË鯬²»×㣬ÎÞ·¨Éý¼¶! soulID=%s,nextLV=%s,pieceItemID=%s,playerPieceCount=%s < %s"   | 
|                                % (soulID, nextLV, pieceItemID, playerPieceCount, needPieceCount), playerID)  | 
|             continue  | 
|           | 
|         if needSoulValue and not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_GatherSoul, needSoulValue, False):  | 
|             GameWorld.DebugLog("¾Û»ê¾«»ª²»×㣬ÎÞ·¨Éý¼¶! soulID=%s,nextLV=%s,needSoulValue=%s" % (soulID, nextLV, needSoulValue), playerID)  | 
|             continue  | 
|           | 
|         GameWorld.DebugLog("¾Û»êÉý¼¶: soulID=%s,nextLV=%s,pieceItemID=%s" % (soulID, nextLV, pieceItemID), playerID)  | 
|         ItemControler.SetItemCountByID(curPlayer, pieceItemID, playerPieceCount - needPieceCount)  | 
|         if needSoulValue:  | 
|             PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_GatherSoul, needSoulValue, "GatherTheSoulUp", {"soulID":soulID, "nextLV":nextLV})  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GatherTheSoulLV % soulID, nextLV)  | 
|           | 
|         # ¼¤»î¶îÍâ´¦Àí  | 
|         if nextLV == 1:  | 
|             pass  | 
|               | 
|         updSoulIDList.append(soulID)  | 
|         if soulID == curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum):  | 
|             holeSoulChange = True  | 
|               | 
|     if not updSoulIDList:  | 
|         GameWorld.DebugLog("ûÓпÉÉý¼¶µÄ¾Û»ê!", playerID)  | 
|         return  | 
|       | 
|     # ³É¾Í  | 
|     colorCountDict = {}  | 
|     totalSoulLV = 0  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|         ipyData = ipyDataMgr.GetGatherTheSoulByIndex(index)  | 
|         soulID = ipyData.GetSoulID()  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         if not soulLV:  | 
|             continue  | 
|         totalSoulLV += soulLV  | 
|         soulColor = ipyData.GetSoulColor()  | 
|         colorCountDict[soulColor] = colorCountDict.get(soulColor, 0) + 1  | 
|           | 
|     for soulColor, soulCount in colorCountDict.items():  | 
|         PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_GatherTheSoulColor, soulCount, [soulColor])  | 
|     PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_GatherTheSoulLV, totalSoulLV)  | 
|       | 
|     Sync_SoulInfo(curPlayer, updSoulIDList)  | 
|     RefreshGatherTheSoulAttr(curPlayer, holeSoulChange)  | 
|     return  | 
|   | 
| def OnGatherTheSoulPuton(curPlayer, soulID):  | 
|     ## ¾Û»ê´©´÷Ìæ»»  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|     if not soulLV:  | 
|         GameWorld.DebugLog("δ¼¤»îÎÞ·¨´©´÷! soulID=%s" % soulID, playerID)  | 
|         return  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("GatherTheSoul", soulID)  | 
|     if not ipyData:  | 
|         return  | 
|     holeNum = ipyData.GetHoleNum()  | 
|     holeSoulID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum)  | 
|     GameWorld.DebugLog("¾Û»ê´©´÷Ìæ»»! soulID=%s,holeNum=%s,holeSoulID=%s" % (soulID, holeNum, holeSoulID), playerID)  | 
|     if holeSoulID == soulID:  | 
|         return  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum, soulID)  | 
|     Sync_SoulHoleInfo(curPlayer)  | 
|     RefreshGatherTheSoulAttr(curPlayer, True)  | 
|     return  | 
|   | 
| def OnGatherTheSoulTakeoff(curPlayer, soulID):  | 
|     ## ¾Û»êжÏ  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("GatherTheSoul", soulID)  | 
|     if not ipyData:  | 
|         return  | 
|     holeNum = ipyData.GetHoleNum()  | 
|     holeSoulID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum)  | 
|     if holeSoulID != soulID:  | 
|         GameWorld.DebugLog("¸Ã¿×ûÓд©´÷¸Ã¾Û»ê£¬ÎÞ·¨Ð¶ÏÂ! soulID=%s,holeNum=%s,holeSoulID=%s" % (soulID, holeNum, holeSoulID), playerID)  | 
|         return  | 
|     GameWorld.DebugLog("¾Û»êжÏÂ! soulID=%s,holeNum=%s" % (soulID, holeNum), playerID)  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum, 0)  | 
|     Sync_SoulHoleInfo(curPlayer)  | 
|     RefreshGatherTheSoulAttr(curPlayer, True)  | 
|     return  | 
|   | 
| def OnGatherTheSoulReset(curPlayer, soulID):  | 
|     ## ¾Û»êÖØÖà  | 
|     ipyData = IpyGameDataPY.GetIpyGameData("GatherTheSoul", soulID)  | 
|     if not ipyData:  | 
|         return  | 
|     holeNum = ipyData.GetHoleNum()  | 
|     pieceItemID = ipyData.GetPieceItemID()  | 
|     if not pieceItemID:  | 
|         return  | 
|     soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|     if soulLV <= 1:  | 
|         GameWorld.DebugLog("¸Ã¾Û»êµÈ¼¶²»ÐèÒªÖØÖÃ! soulID=%s,soulLV=%s" % (soulID, soulLV))  | 
|         return  | 
|       | 
|     costMoneyType, costMoneyValue = 0, 0  | 
|     costMoneyInfo = IpyGameDataPY.GetFuncEvalCfg("GatherTheSoulHole", 2)  | 
|     if costMoneyInfo and len(costMoneyInfo) == 2:  | 
|         costMoneyType, costMoneyValue = costMoneyInfo  | 
|         if not PlayerControl.HaveMoney(curPlayer, costMoneyType, costMoneyValue):  | 
|             return  | 
|           | 
|     resetLV = soulLV  | 
|     pieceTotal = 0  | 
|     soulValueTotal = 0  | 
|     for sLV in range(2, 1 + soulLV)[::-1]:  | 
|         resetIpyData = IpyGameDataPY.GetIpyGameData("GatherTheSoulLV", soulID, sLV)  | 
|         if not resetIpyData:  | 
|             continue  | 
|         resetLV = sLV  | 
|         soulValue = resetIpyData.GetNeedSoulValue()  | 
|         if not soulValue:  | 
|             # ÖØÖõ½²»ÐèÒª¹«¹²²ÄÁϵĵȼ¶  | 
|             break  | 
|         pieceTotal += resetIpyData.GetNeedPiece()  | 
|         soulValueTotal += soulValue  | 
|           | 
|     if resetLV >= soulLV:  | 
|         return  | 
|       | 
|     GameWorld.DebugLog("ÖØÖþۻê: soulID=%s,soulLV=%s,resetLV=%s,pieceTotal=%s,soulValueTotal=%s" % (soulID, soulLV, resetLV, pieceTotal, soulValueTotal))  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_GatherTheSoulLV % soulID, resetLV)  | 
|     if costMoneyType and costMoneyValue:  | 
|         PlayerControl.PayMoney(curPlayer, costMoneyType, costMoneyValue, "GatherTheSoulReset", {"soulID":soulID})  | 
|     ItemControler.GivePlayerItem(curPlayer, pieceItemID, pieceTotal, False, event=["GatherTheSoulReset", False, {"soulID":soulID}])  | 
|     PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_GatherSoul, soulValueTotal, "GatherTheSoulReset", {"soulID":soulID})  | 
|       | 
|     holeSoulChange = (soulID == curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum))  | 
|     Sync_SoulInfo(curPlayer, [soulID])  | 
|     RefreshGatherTheSoulAttr(curPlayer, holeSoulChange)  | 
|     return  | 
|   | 
| def GetGatherTheSoulTotalLV(curPlayer):  | 
|     totalSoulLV = 0  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|         ipyData = ipyDataMgr.GetGatherTheSoulByIndex(index)  | 
|         soulID = ipyData.GetSoulID()  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         if not soulLV:  | 
|             continue  | 
|         totalSoulLV += soulLV  | 
|     return totalSoulLV  | 
|   | 
| def GetHoleSoulColorCount(curPlayer, soulColor, isDownward):  | 
|     ## »ñÈ¡ÏâǶ¾Û»êÆ·ÖʸöÊý  | 
|     colorCount = 0  | 
|     for holeNum in range(1, 1 + IpyGameDataPY.GetFuncCfg("GatherTheSoulHole", 1)):  | 
|         soulID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum)  | 
|         if not soulID:  | 
|             continue  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("GatherTheSoul", soulID)  | 
|         if not ipyData:  | 
|             continue  | 
|         # ÏòϼæÈÝÆ·ÖÊ  | 
|         if isDownward:  | 
|             if ipyData.GetSoulColor() < soulColor:  | 
|                 continue  | 
|         else:  | 
|             if ipyData.GetSoulColor() != soulColor:  | 
|                 continue  | 
|         colorCount += 1  | 
|           | 
|     return colorCount  | 
|       | 
| def RefreshGatherTheSoulSkill(curPlayer):  | 
|     ## Ë¢Ð´©´÷µÄ¾Û»ê¼¼ÄÜÐÅÏ¢  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|       | 
|     soulSkillLVDict = {}  | 
|     for holeNum in range(1, 1 + IpyGameDataPY.GetFuncCfg("GatherTheSoulHole", 1)):  | 
|         soulID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum)  | 
|         if not soulID:  | 
|             continue  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         ipyData = IpyGameDataPY.GetIpyGameData("GatherTheSoul", soulID)  | 
|         if not ipyData:  | 
|             continue  | 
|         skillTypeID = ipyData.GetSoulSkillTypeID()  | 
|         if not skillTypeID:  | 
|             continue  | 
|         skillLVList = ipyData.GetSoulSkillLVList()  | 
|         for skillLV, needSoulLV in enumerate(skillLVList, 1):  | 
|             if soulLV >= needSoulLV:  | 
|                 soulSkillLVDict[skillTypeID] = skillLV  | 
|             else:  | 
|                 break  | 
|               | 
|     #GameWorld.DebugLog("ˢоۻ꼼ÄÜ: %s" % soulSkillLVDict, playerID)  | 
|     skillChange = False    | 
|     playerCtl = PlayerControl.PlayerControl(curPlayer)    | 
|     skillManager = curPlayer.GetSkillManager()  | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|         ipyData = ipyDataMgr.GetGatherTheSoulByIndex(index)  | 
|         holeNum = ipyData.GetHoleNum()  | 
|         skillTypeID = ipyData.GetSoulSkillTypeID()  | 
|         if not skillTypeID:  | 
|             continue  | 
|           | 
|         delSkill = None  | 
|         if skillTypeID in soulSkillLVDict:  | 
|             curSkill = skillManager.FindSkillBySkillTypeID(skillTypeID)  | 
|             if curSkill:  | 
|                 if curSkill.GetSkillLV() != soulSkillLVDict[skillTypeID]:  | 
|                     delSkill = curSkill  | 
|                 else:  | 
|                     # ¼¼ÄÜÏàͬ²»Óô¦Àí  | 
|                     continue  | 
|         else:  | 
|             delSkill = skillManager.FindSkillBySkillTypeID(skillTypeID)  | 
|                               | 
|         # ÏÈɾºó¼Ó  | 
|         if delSkill:  | 
|             skillChange = True  | 
|             skillID = delSkill.GetSkillID()  | 
|             GameWorld.DebugLog("ɾ³ý¾Û»ê¼¼ÄÜ: holeNum=%s,skillID=%s" % (holeNum, skillID), playerID)  | 
|             skillManager.DeleteSkillBySkillID(skillID)  | 
|             playerCtl.RefreshSkillFightPowerByDel(skillID, False)  | 
|               | 
|         if skillTypeID in soulSkillLVDict:  | 
|             skillLV = soulSkillLVDict[skillTypeID]  | 
|             skillData = GameWorld.GetGameData().FindSkillByType(skillTypeID, skillLV)  | 
|             if not skillData:  | 
|                 continue  | 
|             skillChange = True  | 
|             skillID = skillData.GetSkillID()  | 
|             GameWorld.DebugLog("¸üоۻ꼼ÄÜ: holeNum=%s,skillID=%s" % (holeNum, skillID), playerID)  | 
|             skillManager.LearnSkillByID(skillID)  | 
|             playerCtl.RefreshSkillFightPowerEx(skillID, 0, False)  | 
|               | 
|     if skillChange:  | 
|         PassiveBuffEffMng.GetPassiveEffManager().RegistPassiveEff(curPlayer)  | 
|     return  | 
|   | 
| def RefreshGatherTheSoulAttr(curPlayer, refreshSkill=False):  | 
|     if refreshSkill:  | 
|         RefreshGatherTheSoulSkill(curPlayer)  | 
|     CalcSoulAttr(curPlayer)  | 
|     PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()  | 
|     return  | 
|   | 
| def CalcSoulAttr(curPlayer):  | 
|       | 
|     allAttrListSoul = [{} for _ in range(4)] # ¼¤»îµÄ¶¼ËãÊôÐÔ  | 
|       | 
|     ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|     for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|         ipyData = ipyDataMgr.GetGatherTheSoulByIndex(index)  | 
|         soulID = ipyData.GetSoulID()  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         if not soulLV:  | 
|             continue  | 
|         lvIpyData = IpyGameDataPY.GetIpyGameData("GatherTheSoulLV", soulID, soulLV)  | 
|         if not lvIpyData:  | 
|             continue  | 
|         LVAttrTypeList = lvIpyData.GetLVAttrTypeList()  | 
|         LVAttrValueList = lvIpyData.GetLVAttrValueList()  | 
|         for i, attrID in enumerate(LVAttrTypeList):  | 
|             attrValue = LVAttrValueList[i]  | 
|             PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrListSoul)  | 
|               | 
|     #GameWorld.DebugLog("¾Û»êÐÂÊôÐÔ: %s" % allAttrListSoul)  | 
|     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_GatherTheSoul, allAttrListSoul)  | 
|     return  | 
|   | 
| def Sync_SoulInfo(curPlayer, soulIDList=None):  | 
|     if not soulIDList:  | 
|         isForce = False  | 
|         soulIDList = []  | 
|         ipyDataMgr = IpyGameDataPY.IPY_Data()  | 
|         for index in range(ipyDataMgr.GetGatherTheSoulCount()):  | 
|             ipyData = ipyDataMgr.GetGatherTheSoulByIndex(index)  | 
|             soulIDList.append(ipyData.GetSoulID())  | 
|     else:  | 
|         isForce = True  | 
|           | 
|     soulList = []  | 
|     for soulID in soulIDList:  | 
|         soulLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulLV % soulID)  | 
|         if not soulLV and not isForce:  | 
|             continue  | 
|         soulInfo = ChPyNetSendPack.tagMCGatherTheSoul()  | 
|         soulInfo.SoulID = soulID  | 
|         soulInfo.LV = soulLV  | 
|         soulList.append(soulInfo)  | 
|           | 
|     if not soulList:  | 
|         return  | 
|       | 
|     clientPack = ChPyNetSendPack.tagMCGatherTheSoulInfo()  | 
|     clientPack.SoulList = soulList  | 
|     clientPack.Count = len(clientPack.SoulList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return True  | 
|   | 
| def Sync_SoulHoleInfo(curPlayer):  | 
|     holeSoulList = []  | 
|     for holeNum in range(1, 1 + IpyGameDataPY.GetFuncCfg("GatherTheSoulHole", 1)):  | 
|         soulID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GatherTheSoulHoleID % holeNum)  | 
|         holeSoulList.append(soulID)  | 
|     clientPack = ChPyNetSendPack.tagMCGatherTheSoulHoleInfo()  | 
|     clientPack.HoleSoulList = holeSoulList  | 
|     clientPack.Count = len(clientPack.HoleSoulList)  | 
|     NetPackCommon.SendFakePack(curPlayer, clientPack)  | 
|     return  |