| | |
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package Player.PlayerSuccess
|
| | | #
|
| | | # @todo:成就系统
|
| | | # @author xdh
|
| | | # @date 2018-04-23
|
| | | # @author hxp
|
| | | # @date 2025-10-17
|
| | | # @version 1.0
|
| | | #
|
| | | #
|
| | | # 详细描述: 成就系统
|
| | | #
|
| | | #---------------------------------------------------------------------
|
| | | #"""Version = 2018-04-23 11:00"""
|
| | | #---------------------------------------------------------------------
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-10-17 21:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import ShareDefine
|
| | | import ChConfig
|
| | | import GameWorld
|
| | | import ChPyNetSendPack
|
| | | import ShareDefine
|
| | | import NetPackCommon
|
| | | import ItemCommon
|
| | | import IPY_GameWorld
|
| | | import PlayerControl
|
| | | import ChPyNetSendPack
|
| | | import ItemControler
|
| | | import PlayerMagicWeapon
|
| | | import PlayerFamilyRedPacket
|
| | | import PlayerGatherSoul
|
| | | import IpyGameDataPY
|
| | | import PyGameData
|
| | | import EventReport
|
| | | import ObjPool
|
| | |
|
| | | import datetime
|
| | | import time
|
| | | import math
|
| | | import ChEquip
|
| | | import PlayerRune
|
| | | import Operate_EquipStone
|
| | | import Operate_EquipWash
|
| | | import PlayerFeastRedPacket
|
| | | import PlayerDogz
|
| | | import DataRecordPack
|
| | |
|
| | |
|
| | | ## 获取成就字典信息值
|
| | | # @param curPlayer 玩家实例
|
| | | # @return
|
| | | def GetPDictValue(curPlayer, key, defaultValue=0):
|
| | | return curPlayer.NomalDictGetProperty(key, defaultValue, ChConfig.Def_PDictType_Success)
|
| | |
|
| | |
|
| | | ## 设置成就字典信息值
|
| | | # @param curPlayer 玩家实例
|
| | | # @return
|
| | | def SetPDictValue(curPlayer, key, value):
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, key, value, ChConfig.Def_PDictType_Success)
|
| | | return
|
| | |
|
| | | def GetSuccIsFinish(curPlayer, succID):
|
| | | #获取成就是否已完成
|
| | | return GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_FinishTime, succID)
|
| | |
|
| | | def SetSuccFinish(curPlayer, succID, finish=True):
|
| | | #设置成就是否完成
|
| | | return GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_FinishTime, succID, finish)
|
| | |
|
| | | #成就奖励是否已领取
|
| | | def GetSuccHasGot(curPlayer, succID):
|
| | | #获取成就奖励是否已领取
|
| | | return GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_AwardRecord, succID)
|
| | |
|
| | | return GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_SuccessAward, succID)
|
| | | def SetSuccHasGot(curPlayer, succID, hasGot=True):
|
| | | #设置成就奖励领取状态
|
| | | if GetSuccHasGot(curPlayer, succID) == hasGot:
|
| | | return
|
| | | GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_AwardRecord, succID, hasGot)
|
| | | |
| | | if hasGot:
|
| | | #已领取的可设置是否已完成为0
|
| | | SetSuccFinish(curPlayer, succID, 0)
|
| | | |
| | | Sync_SuccTypeIndexAwardRecord(curPlayer, [succID], True) #设置成未领取的在外层同步
|
| | | |
| | | GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_SuccessAward, succID, hasGot)
|
| | | return
|
| | |
|
| | | def GetSuccPassportAwardHasGot(curPlayer, succID):
|
| | | #获取成就通行证奖励是否已领取
|
| | | return GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_PassportAward, succID)
|
| | | def SetSuccPassportAwardHasGot(curPlayer, succID, hasGot=True):
|
| | | #设置成就通行证奖励领取状态
|
| | | GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_Success_PassportAward, succID, hasGot)
|
| | | if hasGot:
|
| | | Sync_SuccTypeIndexAwardRecord(curPlayer, [succID])
|
| | | return
|
| | |
|
| | | def SetSuccFinishValue(curPlayer, succType, condition, value):
|
| | | #设置成就完成度
|
| | | key = ChConfig.Def_PDict_Success_CntValue % (succType, condition)
|
| | | SetPDictValue(curPlayer, key, value)
|
| | | #成就完成进度
|
| | | def GetSuccValue(curPlayer, succType, conds):
|
| | | condition = "" if not conds else str(list(conds)).replace(" ", "")[1:-1]
|
| | | return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SuccessValue % (succType, condition))
|
| | | def SetSuccValue(curPlayer, succType, conds, value):
|
| | | condition = "" if not conds else str(list(conds)).replace(" ", "")[1:-1]
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SuccessValue % (succType, condition), value)
|
| | | return
|
| | |
|
| | | def GetSuccFinishValue(curPlayer, succType, condition):
|
| | | #获取完成度
|
| | | key = ChConfig.Def_PDict_Success_CntValue % (succType, condition)
|
| | | return GetPDictValue(curPlayer, key)
|
| | |
|
| | |
|
| | |
|
| | | ## 成就配表数据类
|
| | | class SuccessData():
|
| | | |
| | | def __init__(self):
|
| | | self.succID = 0 #成就ID
|
| | | self.succType = 0 # 成就类型
|
| | | self.needCnt = 0 # 所以计数数量
|
| | | self.preSuccIDList = [] # 前置成就ID
|
| | | self.condition = [] # 辅助条件(根据类型自定义配置)
|
| | | self.awardItemDict = {} # 完成成就可领取的奖励物品{itemid:itemcnt}
|
| | | self.awardItemDict2 = {} # 完成成就可领取的奖励物品,通行证奖励{itemid:itemcnt}
|
| | | self.moneyDict = {} # 完成成就获得的金钱 {moneyType:money}
|
| | | self.exp = 0 # 完成成就获得的经验
|
| | | self.attrDict = {} # 完成成就获得的属性 {attrid:attrvalue}
|
| | | self.hasAward = True #是否有奖励
|
| | | self.redPacketID = 0 # 红包ID
|
| | | self.magicWeaponExp = {} # 法宝升级经验{id:exp}
|
| | | return
|
| | |
|
| | |
|
| | | ## 成就数据管理类
|
| | | class SuccessDataMng():
|
| | |
|
| | | ## 构造函数
|
| | | # @param None
|
| | | # @return
|
| | | def __init__(self):
|
| | | self.succTypeConditionDict = {} #{succType:[condition,..]}
|
| | | self.successDataDict = {} # {succType:{index:SuccessData(),...}, ...}
|
| | | return
|
| | |
|
| | | ## 加载成就数据
|
| | | # @param succType: 成就类型
|
| | | # @return
|
| | | def __LoadSuccessData(self, succType):
|
| | | if succType in self.successDataDict:
|
| | | return
|
| | | successDataList = IpyGameDataPY.GetIpyGameDataByCondition('Success', {'Type':succType}, True, False)
|
| | | |
| | | if not successDataList:
|
| | | return
|
| | | |
| | | successDataObjDict = {}
|
| | | conditionDict = {}
|
| | | for successIpyData in successDataList:
|
| | | succData = SuccessData()
|
| | | succData.succID = successIpyData.GetID()
|
| | | succData.succType = succType
|
| | | succData.needCnt = successIpyData.GetNeedCnt()
|
| | | succData.preSuccIDList = list(successIpyData.GetPreSuccess())
|
| | | succData.condition = list(successIpyData.GetCondition())
|
| | | succData.awardItemDict = successIpyData.GetAwardItem()
|
| | | succData.awardItemDict2 = successIpyData.GetAwardItem2()
|
| | | succData.moneyDict = successIpyData.GetMoney()
|
| | | succData.exp = successIpyData.GetExp()
|
| | | succData.attrDict = successIpyData.GetAwardAttr()
|
| | | succData.redPacketID = successIpyData.GetRedPacketID()
|
| | | magicWeaponID = successIpyData.GetMagicWeaponID()
|
| | | magicWeaponExp = successIpyData.GetMagicWeaponExp()
|
| | | if magicWeaponID and magicWeaponExp:
|
| | | succData.magicWeaponExp[magicWeaponID] = magicWeaponExp
|
| | | succData.hasAward = bool(succData.awardItemDict or succData.moneyDict or succData.exp or succData.attrDict or succData.redPacketID or succData.magicWeaponExp \
|
| | | or succData.awardItemDict2)
|
| | | successDataObjDict[succData.succID]=succData
|
| | | if tuple(succData.condition) not in conditionDict:
|
| | | conditionDict[tuple(succData.condition)] = [succData.succID]
|
| | | else:
|
| | | conditionDict[tuple(succData.condition)].append(succData.succID)
|
| | | |
| | | self.successDataDict[succType] = successDataObjDict
|
| | | #self.succTypeConditionDict[succType] = conditionDict
|
| | | return
|
| | | |
| | | ## 根据成就类型获取该类型所有成就
|
| | | # @param succType: 成就类型
|
| | | # @return: {index:SuccessData(), ...}
|
| | | def GetSuccDataByType(self, succType):
|
| | | if succType not in self.successDataDict:
|
| | | self.__LoadSuccessData(succType)
|
| | | return self.successDataDict.get(succType, {}).values()
|
| | | |
| | | ## 根据成就类型获取该类型所有条件
|
| | | # @param succType: 成就类型
|
| | | # @return: {index:SuccessData(), ...}
|
| | | # def GetConditionDictByType(self, succType):
|
| | | # if succType not in self.succTypeConditionDict:
|
| | | # self.__LoadSuccessData(succType)
|
| | | # return self.succTypeConditionDict.get(succType, {})
|
| | |
|
| | | ## 根据成就类型索引获取某个成就数据
|
| | | # @param succType: 成就类型
|
| | | # @param index: 成就索引
|
| | | # @return: SuccessData() or None
|
| | | def GetSuccessData(self, succID):
|
| | | succIpyData = IpyGameDataPY.GetIpyGameDataNotLog('Success', succID)
|
| | | if not succIpyData:
|
| | | return
|
| | | succType = succIpyData.GetType()
|
| | | if succType not in self.successDataDict:
|
| | | self.__LoadSuccessData(succType)
|
| | | return self.successDataDict.get(succType, {}).get(succID)
|
| | | |
| | | |
| | | |
| | |
|
| | | g_succDataMng = SuccessDataMng()
|
| | |
|
| | |
|
| | | ## 获取成就数据管理器
|
| | | # @param None
|
| | | # @return
|
| | | def GetSuccDataMng():
|
| | | return g_succDataMng
|
| | |
|
| | | ## 成就OnLogin
|
| | | # @param curPlayer
|
| | | # @return
|
| | | def SuccOnLogin(curPlayer):
|
| | | # 同步成就信息
|
| | | Sync_SuccessInfo(curPlayer)
|
| | | # 同步成就领奖记录
|
| | | Sync_SuccTypeIndexAwardRecord(curPlayer)
|
| | | |
| | | |
| | | # 检查老玩家
|
| | | __CheckOldPlayerSuccess(curPlayer)
|
| | | |
| | | # 检查达成与否(有些可能改过上限,然后玩家可以完成,上线统一做一次检查)
|
| | | for succType in ShareDefine.SuccessTypeList:
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(succType)
|
| | | if not succInfoList:
|
| | | continue
|
| | | __DoCheckSuccessFinish(curPlayer, succType, succInfoList)
|
| | | |
| | | if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Success_ScoreAward):
|
| | | Sync_SuccessScoreAward(curPlayer)
|
| | | SyncSuccessInfo(curPlayer)
|
| | | SyncSuccessAwardRecord(curPlayer)
|
| | | return
|
| | |
|
| | | ## 检查老玩家成就激活情况
|
| | | # @param None
|
| | | # @return
|
| | | def __CheckOldPlayerSuccess(curPlayer):
|
| | | ''' 成就版本更新老玩家检查 每次启动服务后 玩家第一次上线检查成就完成情况
|
| | | '''
|
| | | initGameWorldTime = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_InitGameWorldTime)
|
| | | # 上线需要检查老玩家成就完成情况类型
|
| | | NeedCheckSuccTypeList = [
|
| | | ]
|
| | | |
| | | curCheckVersion = GetPDictValue(curPlayer, ChConfig.Def_PDict_Success_CheckVersion)
|
| | | if curCheckVersion == initGameWorldTime:
|
| | | GameWorld.DebugLog(' 本次开启服务器处理过成就检查,不再处理 ', curPlayer.GetID())
|
| | | def ResetSuccessByType(curPlayer, succType, ignoreFinish=True):
|
| | | #重置某类型成就进度,一般用于先重置次数再重新计数,或者活动类
|
| | | ipyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("Success", succType)
|
| | | if not ipyDataList:
|
| | | return
|
| | | GameWorld.DebugLog("更新老玩家上线检查成就curCheckVersion=%s" % (curCheckVersion))
|
| | | ipyDataMgr = IpyGameDataPY.IPY_Data()
|
| | | for succType in NeedCheckSuccTypeList:
|
| | | pass
|
| | | |
| | | DataRecordPack.DR_CheckOldPlayerSuccess(curPlayer)
|
| | | SetPDictValue(curPlayer, ChConfig.Def_PDict_Success_CheckVersion, initGameWorldTime)
|
| | | GameWorld.DebugLog("更新老玩家上线检查成就updCheckVersions=%s" % (initGameWorldTime), curPlayer.GetID())
|
| | | return
|
| | |
|
| | | ## 成就OnWeek
|
| | | # @param curPlayer
|
| | | # @return
|
| | | def OnWeek(curPlayer):
|
| | | resetList = []
|
| | | weekResetSuccTypeList = IpyGameDataPY.GetFuncEvalCfg('WeekResetSuccType')
|
| | | for succType in weekResetSuccTypeList:
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(succType)
|
| | | if not succInfoList:
|
| | | for ipyData in ipyDataList:
|
| | | succID = ipyData.GetSuccID()
|
| | | if ignoreFinish and GetSuccHasGot(curPlayer, succID):
|
| | | continue
|
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | condition = succDataObj.condition
|
| | | if not GetSuccFinishValue(curPlayer, succType, condition):
|
| | | continue
|
| | | SetSuccFinishValue(curPlayer, succType, condition, 0)
|
| | | SetSuccFinish(curPlayer, succID, False)
|
| | | SetSuccHasGot(curPlayer, succID, False)
|
| | | resetList.append(succID)
|
| | | GameWorld.DebugLog(" OnWeek 重置成就类型: succID=%s" % (succID))
|
| | | if resetList:
|
| | | Sync_SuccTypeIndexAwardRecord(curPlayer, resetList, True)
|
| | | Sync_SuccessInfo(curPlayer, resetList, True)
|
| | | conds = ipyData.GetCondition()
|
| | | SetSuccValue(curPlayer, succType, conds, 0)
|
| | | return
|
| | |
|
| | | def DoResetSuccessIDList(curPlayer, resetSuccIDList):
|
| | | ## 重置成就相关数据
|
| | | if not resetSuccIDList:
|
| | | return
|
| | | resetList = []
|
| | | for succID in resetSuccIDList:
|
| | | succData = GetSuccDataMng().GetSuccessData(succID)
|
| | | if not succData:
|
| | | continue
|
| | | succType = succData.succType
|
| | | condition = succData.condition
|
| | | #if not GetSuccFinishValue(curPlayer, succType, condition):
|
| | | # continue
|
| | | SetSuccFinishValue(curPlayer, succType, condition, 0)
|
| | | SetSuccFinish(curPlayer, succID, False)
|
| | | SetSuccHasGot(curPlayer, succID, False)
|
| | | resetList.append(succID)
|
| | | GameWorld.DebugLog(" 重置成就类型: succType=%s,succID=%s" % (succType, succID))
|
| | | if resetList:
|
| | | Sync_SuccTypeIndexAwardRecord(curPlayer, resetList, True)
|
| | | Sync_SuccessInfo(curPlayer, resetList, True)
|
| | | return
|
| | | #def UpdateSuccessProgressByConditions(curPlayer, successType, conditionCountDict):
|
| | | # ## 根据多种条件更新进度,如装备多品质的
|
| | | # ipyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("Success", successType)
|
| | | # if not ipyDataList:
|
| | | # return
|
| | | # updIDList = []
|
| | | # updsuccDataList = []
|
| | | # updConditionDict = {}
|
| | | # |
| | | # for condition, newCount in conditionCountDict.items():
|
| | | # addCondList = [] # 不同的成就ID条件可能相同,只是最大进度不同,故传入的条件计数针对相同成就条件只能累加一次
|
| | | # for ipyData in ipyDataList:
|
| | | # succID = ipyData.GetSuccID()
|
| | | # conds = ipyData.GetCondition()
|
| | | # needCnt = ipyData.GetNeedCnt()
|
| | | # |
| | | # tupleCond = tuple(conds) # 作为字典key用
|
| | | # |
| | | # if tupleCond not in updConditionDict:
|
| | | # updConditionDict[tupleCond] = [conds, 0, 0] # [条件, 更新值, 最大进度值]
|
| | | # updInfo = updConditionDict[tupleCond]
|
| | | # if updInfo[2] < needCnt:
|
| | | # updInfo[2] = needCnt
|
| | | # |
| | | # if not __CheckCanAddSuccess(curPlayer, ipyData, list(condition)):
|
| | | # continue
|
| | | # |
| | | # if succID not in updIDList:
|
| | | # updIDList.append(succID)
|
| | | # updsuccDataList.append(ipyData)
|
| | | # |
| | | # if tupleCond not in addCondList:
|
| | | # addCondList.append(tupleCond)
|
| | | # updConditionDict[tupleCond][1] = updConditionDict[tupleCond][1] + newCount # 更新进度值
|
| | | # |
| | | # # 没有找到更新目标不处理
|
| | | # #GameWorld.DebugLog(" updConditionDict=%s" % updConditionDict)
|
| | | # #GameWorld.DebugLog(" updIDList=%s" % updIDList)
|
| | | # if not updIDList:
|
| | | # return
|
| | | # |
| | | # # 先更新成就记录值后再判断完成与否
|
| | | # for cond, updCnt, maxCnt in updConditionDict.values():
|
| | | # if not updCnt:
|
| | | # continue
|
| | | # updCnt = min(maxCnt, updCnt)
|
| | | # if GetSuccValue(curPlayer, successType, cond) == updCnt:
|
| | | # continue
|
| | | # SetSuccValue(curPlayer, successType, cond, updCnt)
|
| | | # SyncSuccessInfo(curPlayer, syncTypeCondList)
|
| | | # return
|
| | |
|
| | | ## 成就OnDay
|
| | | # @param curPlayer
|
| | | # @return
|
| | | def SuccOnDay(curPlayer):
|
| | | resetList = []
|
| | | # 重置连续类型断掉的数据
|
| | | serverDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay)
|
| | | GameWorld.DebugLog("连续类型成就过天...serverDay=%s" % serverDay)
|
| | | for succType in ShareDefine.ContinueSuccessTypeList:
|
| | | |
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(succType)
|
| | | |
| | | if not succInfoList:
|
| | | continue
|
| | | |
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | condition = succDataObj.condition
|
| | | #GameWorld.DebugLog(" succID=%s" % (succID))
|
| | | |
| | | finishTime = GetSuccIsFinish(curPlayer, succID)
|
| | | |
| | | # 已完成的不再检查
|
| | | if finishTime > 0 or GetSuccHasGot(curPlayer, succID):
|
| | | GameWorld.DebugLog(" 已完成的不再检查")
|
| | | continue
|
| | | |
| | | if __DoCheckResetContinue(curPlayer, serverDay, succID):
|
| | | SetSuccFinishValue(curPlayer, succType, condition, 0)
|
| | | resetList.append(succID)
|
| | | |
| | | if resetList:
|
| | | Sync_SuccessInfo(curPlayer, resetList, True)
|
| | | return
|
| | |
|
| | | ## 检查成就连续天情况
|
| | | # @param curPlayer
|
| | | # @return True-连续已中断
|
| | | def __DoCheckResetContinue(curPlayer, serverDay, succID):
|
| | | lastDayKey = ChConfig.Def_PDict_Success_LastDay % (succID)
|
| | | lastDay = GetPDictValue(curPlayer, lastDayKey)
|
| | | |
| | | # 记录时间从开服天数改成 time.time()
|
| | | if lastDay <= 1000:
|
| | | #GameWorld.DebugLog(" lastDay <= 0")
|
| | | return
|
| | | |
| | | tick = int(time.time())
|
| | | serverDay = GameWorld.ChangeTimeNumToDatetime(tick, ChConfig.TYPE_Time_Format_Day)
|
| | | lastDay = GameWorld.ChangeTimeNumToDatetime(lastDay, ChConfig.TYPE_Time_Format_Day)
|
| | | # 昨天有更新的不处理,证明还是连续状态
|
| | | if lastDay == serverDay - datetime.timedelta(1):
|
| | | GameWorld.DebugLog(" 昨天有更新的不处理,证明还是连续状态")
|
| | | return
|
| | | |
| | | |
| | | SetPDictValue(curPlayer, lastDayKey, 0)
|
| | | GameWorld.DebugLog(" 重置成就连续类型: succID=%s" % (succID))
|
| | | return True
|
| | |
|
| | | def ResetSuccessByType(curPlayer, succType):
|
| | | #重置某类型成就进度(已完成的不重置)
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(succType)
|
| | | if not succInfoList:
|
| | | return
|
| | | #先重置次数再重新计数
|
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | condition = succDataObj.condition
|
| | | #GameWorld.DebugLog(" succID=%s" % (succID))
|
| | | finishTime = GetSuccIsFinish(curPlayer, succID)
|
| | | # 已完成的不再检查
|
| | | if finishTime > 0 or GetSuccHasGot(curPlayer, succID):
|
| | | continue
|
| | | SetSuccFinishValue(curPlayer, succType, condition, 0)
|
| | | return
|
| | |
|
| | | def DoEquipSuccessLogic(curPlayer, classLV):
|
| | | #玩家当前可装备的装备类型
|
| | | |
| | | ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('EquipPlaceIndexMap', {'ClassLV':classLV}, True)
|
| | | def UptateSuccessProgress(curPlayer, successType, newCnt, condition=[]):
|
| | | ipyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("Success", successType)
|
| | | if not ipyDataList:
|
| | | return
|
| | |
|
| | | placeCountDict, colorCountDict, suitCountDict = {}, {}, {}
|
| | | playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
|
| | | curCnt = None
|
| | | for ipyData in ipyDataList:
|
| | | equipIndex = ipyData.GetGridIndex()
|
| | | curEquip = playerEquip.GetAt(equipIndex)
|
| | | if curEquip.IsEmpty():
|
| | | if not __CheckCanAddSuccess(curPlayer, ipyData, condition):
|
| | | continue
|
| | | itemPlace = curEquip.GetEquipPlace()
|
| | | |
| | | # 套装、颜色 成就 统计基础部位
|
| | | if itemPlace in ChConfig.EquipPlace_Base:
|
| | | itemColor = curEquip.GetItemColor()
|
| | | colorConditionKey = (classLV, itemColor)
|
| | | colorCountDict[colorConditionKey] = colorCountDict.get(colorConditionKey, 0) + 1
|
| | | |
| | | # 统计套装数
|
| | | if curEquip.GetSuiteID():
|
| | | suitConditionKey = (classLV, )
|
| | | suitCountDict[suitConditionKey] = suitCountDict.get(suitConditionKey, 0) + 1
|
| | | |
| | | # 部位 成就 统计特殊部位
|
| | | elif itemPlace in ChConfig.EquipPlace_Special:
|
| | | placeConditionKey = (classLV, itemPlace)
|
| | | placeCountDict[placeConditionKey] = placeCountDict.get(placeConditionKey, 0) + 1
|
| | | |
| | | # 更新成就
|
| | | #GameWorld.DebugLog("装备阶部位成就数据: classLV=%s,placeCountDict=%s" % (classLV, placeCountDict))
|
| | | UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipPlace, placeCountDict)
|
| | | |
| | | #GameWorld.DebugLog("装备阶颜色成就数据: classLV=%s,colorCountDict=%s" % (classLV, colorCountDict))
|
| | | UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipColorItem, colorCountDict)
|
| | | |
| | | #GameWorld.DebugLog("装备阶套装成就数据: classLV=%s,suitCountDict=%s" % (classLV, suitCountDict))
|
| | | UpdateSuccessProgressByConditions(curPlayer, ShareDefine.SuccType_EquipSuit, suitCountDict)
|
| | | return
|
| | |
|
| | | def UpdateSuccessProgressByConditions(curPlayer, successType, conditionCountDict):
|
| | | if successType not in ShareDefine.SuccessTypeList:
|
| | | return
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(successType)
|
| | | if not succInfoList:
|
| | | return
|
| | | updIDList = []
|
| | | updsuccDataList = []
|
| | | updConditionDict = {}
|
| | | |
| | | for condition, newCount in conditionCountDict.items():
|
| | | addCondList = [] # 不同的成就ID条件可能相同,只是最大进度不同,故传入的条件计数针对相同成就条件只能累加一次
|
| | | for succDataObj in succInfoList:
|
| | | cond = succDataObj.condition
|
| | | |
| | | tupleCond = tuple(cond) # 作为字典key用
|
| | | succID = succDataObj.succID
|
| | | needCnt = succDataObj.needCnt
|
| | | |
| | | if tupleCond not in updConditionDict:
|
| | | updConditionDict[tupleCond] = [cond, 0, 0] # [条件, 更新值, 最大进度值]
|
| | | updInfo = updConditionDict[tupleCond]
|
| | | if updInfo[2] < needCnt:
|
| | | updInfo[2] = needCnt
|
| | | |
| | | if not __CheckCanAddSuccess(curPlayer, succDataObj, list(condition)):
|
| | | continue
|
| | | |
| | | if succID not in updIDList:
|
| | | updIDList.append(succID)
|
| | | updsuccDataList.append(succDataObj)
|
| | | |
| | | if tupleCond not in addCondList:
|
| | | addCondList.append(tupleCond)
|
| | | updConditionDict[tupleCond][1] = updConditionDict[tupleCond][1] + newCount # 更新进度值
|
| | | |
| | | # 没有找到更新目标不处理
|
| | | #GameWorld.DebugLog(" updConditionDict=%s" % updConditionDict)
|
| | | #GameWorld.DebugLog(" updIDList=%s" % updIDList)
|
| | | if not updIDList:
|
| | | return
|
| | | |
| | | isUpd = False
|
| | | # 先更新成就记录值后再判断完成与否
|
| | | for cond, updCnt, maxCnt in updConditionDict.values():
|
| | | if not updCnt:
|
| | | continue
|
| | | updCnt = min(maxCnt, updCnt)
|
| | | if GetSuccFinishValue(curPlayer, successType, cond) == updCnt:
|
| | | continue
|
| | | isUpd = True
|
| | | SetSuccFinishValue(curPlayer, successType, cond, updCnt)
|
| | | #GameWorld.DebugLog(" successType=%s,cond=%s,updCnt=%s,maxCnt=%s" % (successType, cond, updCnt, maxCnt))
|
| | | |
| | | if not isUpd:
|
| | | return
|
| | | |
| | | # 同步更新信息
|
| | | Sync_SuccessInfo(curPlayer, updIDList, False)
|
| | | |
| | | # 更新值后检查成就完成情况
|
| | | __DoCheckSuccessFinish(curPlayer, successType, updsuccDataList)
|
| | | return
|
| | |
|
| | |
|
| | | ## 更新成就完成进度逻辑(外部功能调用,只适用于不重置的成就类型)
|
| | | # @param curPlayer
|
| | | # @param successType: 成就类型
|
| | | # @param newCnt: 新进度值
|
| | | # @return
|
| | | def UptateSuccessProgress(curPlayer, successType, newCnt, condition=[]):
|
| | | if successType not in ShareDefine.SuccessTypeList:
|
| | | return
|
| | | if successType in ShareDefine.FeastRedPackSuccessTypeList:
|
| | | if not PlayerFeastRedPacket.GetFeastRedPacketState():
|
| | | return
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(successType)
|
| | | if not succInfoList:
|
| | | GameWorld.DebugLog(" 找不到成就数据successType=%s" % successType)
|
| | | return
|
| | | curCnt = -1
|
| | | for succData in succInfoList:
|
| | | if not __CheckCanAddSuccess(curPlayer, succData, condition):
|
| | | continue
|
| | | curCnt = GetSuccFinishValue(curPlayer, successType, succData.condition)
|
| | | curCnt = GetSuccValue(curPlayer, successType, ipyData.GetCondition())
|
| | | break
|
| | | |
| | | if curCnt == -1:
|
| | | |
| | | if curCnt == None or newCnt <= curCnt:
|
| | | #GameWorld.DebugLog("不需要更新成就值: curCnt=%s" % (curCnt))
|
| | | return
|
| | | if newCnt > curCnt: #这里需要立即更新!!
|
| | | DoAddSuccessProgress(curPlayer, successType, newCnt - curCnt, condition, False)
|
| | | #update的需要立即更新!!
|
| | | DoAddSuccessProgress(curPlayer, successType, newCnt - curCnt, condition, False)
|
| | | return
|
| | |
|
| | | def __CheckCanAddSuccess(curPlayer, succDataObj, condition):
|
| | | successType = succDataObj.succType
|
| | | succID = succDataObj.succID
|
| | | cond = succDataObj.condition
|
| | | |
| | | if successType in ShareDefine.FeastRedPackSuccessTypeList:
|
| | | todayFeastSuccIDList = PlayerFeastRedPacket.GetTodayFeastSuccIDList()
|
| | | if not todayFeastSuccIDList or succID not in todayFeastSuccIDList:
|
| | | #GameWorld.DebugLog(" 非今日节日红包成就,不增加进度! succID=%s,todayFeastSuccIDList=%s" % (succID, todayFeastSuccIDList))
|
| | | return
|
| | | isUnDownCheck = successType in ShareDefine.UnDownCheckSuccessTypeList
|
| | | isContain = successType in ShareDefine.ContainSuccessTypeList
|
| | | def __CheckCanAddSuccess(curPlayer, ipyData, condition):
|
| | | ## 检查可否添加进度
|
| | | succID = ipyData.GetSuccID()
|
| | | # 已完成的不再检查
|
| | | if GetSuccIsFinish(curPlayer, succID) or GetSuccHasGot(curPlayer, succID):
|
| | | if GetSuccHasGot(curPlayer, succID):
|
| | | return
|
| | | #前置成就判断
|
| | | preSuccIDList = succDataObj.preSuccIDList
|
| | | for preSuccID in preSuccIDList:
|
| | | if not GetSuccIsFinish(curPlayer, preSuccID) and not GetSuccHasGot(curPlayer, preSuccID):
|
| | | return
|
| | |
|
| | | # 有辅助条件的, 需判断是否向下检查
|
| | | if len(cond) > 0:
|
| | | if isContain:
|
| | | if condition[0] not in cond:
|
| | | successType = ipyData.GetSuccType()
|
| | | conds = ipyData.GetCondition()
|
| | | if not conds:
|
| | | # 无条件的默认可添加
|
| | | return True
|
| | | |
| | | if not condition:
|
| | | return
|
| | | |
| | | # 传进来的条件满足配置的条件列表中的一个就行的成就类型
|
| | | if successType in ShareDefine.ContainSuccessTypeList:
|
| | | if condition[0] not in conds:
|
| | | return
|
| | | |
| | | # 传进来的条件是配置条件的整数倍的成就类型
|
| | | elif successType in ShareDefine.MultipleSuccessTypeList:
|
| | | if not (condition[0] / conds[0] and condition[0] % conds[0] == 0):
|
| | | #必须是条件的倍数
|
| | | return
|
| | | |
| | | else:
|
| | | if len(conds) != len(condition):
|
| | | return
|
| | | # 不向下检查增加进度的, 仅配置值等于该值的可增加进度
|
| | | if successType in ShareDefine.UnDownCheckSuccessTypeList:
|
| | | if conds != condition:
|
| | | return
|
| | | elif successType in ShareDefine.MultipleSuccessTypeList:
|
| | | if not (condition[0]/cond[0] and condition[0]%cond[0] == 0):
|
| | | #必须是条件的倍数
|
| | | return
|
| | | # 可向下增加进度的, 仅配置值 <= 该值的可增加进度
|
| | | else:
|
| | | if len(cond) != len(condition):
|
| | | return
|
| | | # 不向下检查增加进度的, 仅配置值等于该值的可增加进度
|
| | | if isUnDownCheck and cond != condition:
|
| | | return
|
| | | # 可向下增加进度的, 仅配置值 <= 该值的可增加进度
|
| | | if not isUnDownCheck:
|
| | | isbreak = False
|
| | | undowncheckIndexList = [] # 不向下检查的条件索引
|
| | | if successType in ShareDefine.PartUnDownCheckSuccessTypeInfo:
|
| | | undowncheckIndexList = ShareDefine.PartUnDownCheckSuccessTypeInfo[successType]
|
| | | for i, num in enumerate(cond):
|
| | | if i in undowncheckIndexList:
|
| | | if num != condition[i]:
|
| | | isbreak = True
|
| | | break
|
| | | if num > condition[i]:
|
| | | isbreak = False
|
| | | undowncheckIndexList = [] # 不向下检查的条件索引
|
| | | if successType in ShareDefine.PartUnDownCheckSuccessTypeInfo:
|
| | | undowncheckIndexList = ShareDefine.PartUnDownCheckSuccessTypeInfo[successType]
|
| | | for i, num in enumerate(conds):
|
| | | if i in undowncheckIndexList:
|
| | | if num != condition[i]:
|
| | | isbreak = True
|
| | | break
|
| | | if isbreak:
|
| | | return
|
| | | if num > condition[i]:
|
| | | isbreak = True
|
| | | break
|
| | | if isbreak:
|
| | | return
|
| | | |
| | | return True
|
| | |
|
| | |
|
| | | # 将攻击类的成就一次执行,减少运行量
|
| | | def FinishDelayAddSuccessProgress(curPlayer, tick, isFinish=True):
|
| | | # 将攻击类的成就一次执行,减少运行量
|
| | |
|
| | | if not isFinish:
|
| | | # 二次延迟处理
|
| | |
| | |
|
| | | successDict = PyGameData.g_delaySuccessDict.pop(playerID)
|
| | | for sucessInfo, cnt in successDict.items():
|
| | |
|
| | | DoAddSuccessProgress(curPlayer, sucessInfo[0], cnt, list(sucessInfo[1]), False)
|
| | |
|
| | | |
| | | return
|
| | |
|
| | |
|
| | | ## 增加成就完成进度逻辑(外部功能调用)
|
| | | # @param curPlayer
|
| | | # @param successType: 成就类型
|
| | | # @param addCnt: 增加进度值
|
| | | # @param condition: 扩展条件
|
| | | # @return
|
| | | def DoAddSuccessProgress(curPlayer, successType, addCnt, condition=[], delayCalc=True):
|
| | | #GameWorld.DebugLog("DoAddSuccessProgress type=%s,addCnt=%s,condition=%s" |
| | | # % (successType, addCnt, condition), curPlayer.GetPlayerID())
|
| | | if GameWorld.IsCrossServer():
|
| | | return
|
| | |
|
| | | if successType in ShareDefine.FeastRedPackSuccessTypeList:
|
| | | if not PlayerFeastRedPacket.GetFeastRedPacketState():
|
| | | #GameWorld.DebugLog("非节日红包活动时间,不增加成就!successType=%s" % successType)
|
| | | return
|
| | | |
| | | playerID = curPlayer.GetID()
|
| | | if delayCalc and successType not in ShareDefine.NeedResetSuccessTypeList:
|
| | | if delayCalc:
|
| | | if playerID not in PyGameData.g_delaySuccessDict:
|
| | | PyGameData.g_delaySuccessDict[playerID] = {}
|
| | | |
| | | # 最终处理减少计算量
|
| | | # 最终处理减少计算量,短时间多次累加汇总一次计算
|
| | | successTuple = (successType, tuple(condition))
|
| | | if successTuple not in PyGameData.g_delaySuccessDict[playerID]:
|
| | | PyGameData.g_delaySuccessDict[playerID][successTuple] = addCnt
|
| | | else:
|
| | | PyGameData.g_delaySuccessDict[playerID][successTuple] = PyGameData.g_delaySuccessDict[playerID][successTuple] + addCnt
|
| | | |
| | | return
|
| | |
|
| | |
|
| | | |
| | | if condition and type(condition) != type([]):
|
| | | GameWorld.ErrLog('DoAddSuccessProgress type=%s, condition=%s 错误!'%(type, condition))
|
| | | GameWorld.ErrLog('DoAddSuccessProgress type=%s, condition=%s 错误!' % (type, condition))
|
| | | return
|
| | | if successType not in ShareDefine.SuccessTypeList:
|
| | | return
|
| | |
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(successType)
|
| | | if not succInfoList:
|
| | | GameWorld.DebugLog(" 找不到成就数据successType=%s" % successType)
|
| | | ipyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("Success", successType)
|
| | | if not ipyDataList:
|
| | | GameWorld.DebugLog("找不到成就数据successType=%s" % successType)
|
| | | return
|
| | |
|
| | | maxCnt = 0 # 本次可以更新到的最大值
|
| | | updConditionList = [] # 需更新进度值的key编号列表
|
| | | updIDList = []
|
| | | updsuccDataList = []
|
| | | tick = int(time.time())
|
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | needCnt = succDataObj.needCnt
|
| | | for ipyData in ipyDataList:
|
| | |
|
| | | if not __CheckCanAddSuccess(curPlayer, succDataObj, condition):
|
| | | if not __CheckCanAddSuccess(curPlayer, ipyData, condition):
|
| | | continue
|
| | | updIDList.append(succID)
|
| | | updsuccDataList.append(succDataObj)
|
| | | curCondition = succDataObj.condition
|
| | | if curCondition not in updConditionList:
|
| | | updConditionList.append(curCondition)
|
| | | |
| | | conds = ipyData.GetCondition()
|
| | | if conds not in updConditionList:
|
| | | updConditionList.append(conds)
|
| | |
|
| | | needCnt = ipyData.GetNeedCnt()
|
| | | if maxCnt < needCnt:
|
| | | maxCnt = needCnt
|
| | |
|
| | | # 连续类型的, 更新连续时的开服天数
|
| | | if successType in ShareDefine.ContinueSuccessTypeList:
|
| | | lastDayKey = ChConfig.Def_PDict_Success_LastDay % (succID)
|
| | | SetPDictValue(curPlayer, lastDayKey, tick)
|
| | | |
| | | |
| | | |
| | | #GameWorld.DebugLog(" updConditionList=%s,maxCnt=%s" % (str(updConditionList), maxCnt))
|
| | | |
| | | # 没有找到更新目标不处理
|
| | | if not updConditionList or maxCnt <= 0:
|
| | | return
|
| | |
|
| | | # 先更新成就记录值后再判断完成与否
|
| | | for condition in updConditionList:
|
| | | curCnt = GetSuccFinishValue(curPlayer, successType, condition)
|
| | | syncTypeCondList = []
|
| | | for conds in updConditionList:
|
| | | curCnt = GetSuccValue(curPlayer, successType, conds)
|
| | | updCnt = min(maxCnt, curCnt + addCnt)
|
| | | SetSuccFinishValue(curPlayer, successType, condition, updCnt)
|
| | | # GameWorld.DebugLog(" successType=%s,condition=%s,curCnt=%s,addCnt=%s,updCnt=%s" |
| | | # % (successType,condition, curCnt, addCnt, updCnt))
|
| | | |
| | | |
| | | # 同步更新信息
|
| | | Sync_SuccessInfo(curPlayer, updIDList, False)
|
| | | |
| | | # 更新值后检查成就完成情况
|
| | | __DoCheckSuccessFinish(curPlayer, successType, updsuccDataList)
|
| | | SetSuccValue(curPlayer, successType, conds, updCnt)
|
| | | syncTypeCondList.append([successType, conds])
|
| | | SyncSuccessInfo(curPlayer, syncTypeCondList)
|
| | | return
|
| | |
|
| | |
|
| | | ## 检查成就完成情况
|
| | | # @param curPlayer
|
| | | # @param successType: 成就类型
|
| | | # @param succInfoDict: 该类型所有成就信息字典
|
| | | # @param isPub: 进度值是否公共
|
| | | # @param updNumList: 有更新进度的编号列表
|
| | | # @return
|
| | | def __DoCheckSuccessFinish(curPlayer, successType, succInfoList):
|
| | | def GetSuccessAward(curPlayer, succID):
|
| | | ipyData = IpyGameDataPY.GetIpyGameDataByCondition("Success", {"SuccID":succID})
|
| | | if not ipyData:
|
| | | return
|
| | |
|
| | | isNeedSys = successType in [ShareDefine.SuccType_ElderBattlefieldKill, ShareDefine.SuccType_ElderBattlefieldConKill]
|
| | | curTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCurrentDataTimeStr())
|
| | | playerName = curPlayer.GetName()
|
| | |
|
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | needCnt = succDataObj.needCnt
|
| | | |
| | | finishTime = GetSuccIsFinish(curPlayer, succID)
|
| | | |
| | | # 已完成的不再检查
|
| | | if finishTime > 0 or GetSuccHasGot(curPlayer, succID):
|
| | | continue
|
| | | |
| | | curCnt = GetSuccFinishValue(curPlayer, successType, succDataObj.condition)
|
| | | |
| | | # 完成成就
|
| | | if curCnt >= needCnt:
|
| | | # 设置完成时间
|
| | | SetSuccFinish(curPlayer, succID)
|
| | | # 没有奖励的直接设置已领取
|
| | | if not succDataObj.hasAward:
|
| | | SetSuccHasGot(curPlayer, succID)
|
| | | |
| | | # 通知客户端完成成就
|
| | | Notify_FinishSuccess(curPlayer, succID, curTime)
|
| | | |
| | | if isNeedSys:
|
| | | PlayerControl.WorldNotify(0, 'AncientBattlefield_1', [playerName, succID])
|
| | | |
| | | for mwID in succDataObj.magicWeaponExp.keys():
|
| | | EventReport.WriteEvent_MWSuccess(curPlayer, mwID, succID, ChConfig.CME_Log_Start)
|
| | | GameWorld.DebugLog(" 完成成就succID=%s, type=%s,time=%s" |
| | | % (succID, successType, curTime))
|
| | | |
| | | |
| | | if GetSuccHasGot(curPlayer, succID):
|
| | | GameWorld.DebugLog("该成就奖励已经领取过! succID=%s" % succID)
|
| | | return
|
| | |
|
| | | succType = ipyData.GetSuccType()
|
| | | conds = ipyData.GetCondition()
|
| | | needCnt = ipyData.GetNeedCnt()
|
| | | curValue = GetSuccValue(curPlayer, succType, conds)
|
| | | if curValue < needCnt:
|
| | | GameWorld.DebugLog("该成就未完成! succID=%s,curValue=%s < %s" % (succID, curValue, needCnt))
|
| | | return
|
| | | |
| | | SetSuccHasGot(curPlayer, succID)
|
| | | SyncSuccessAwardRecord(curPlayer, [succID], True)
|
| | | |
| | | awardItemList = ipyData.GetAwardItemList()
|
| | | if awardItemList:
|
| | | ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["SuccessAward", False, {}])
|
| | | return
|
| | |
|
| | |
|
| | | ## 计算成就属性
|
| | | # @param curPlayer 玩家
|
| | | # @param allAttrList 属性列表
|
| | | # @return None
|
| | | def CalcSuccessAttr(curPlayer):
|
| | | allAttrList = [{} for _ in range(4)]
|
| | | attrDict = {}
|
| | | ipyDataMgr = IpyGameDataPY.IPY_Data()
|
| | | for i in xrange(ipyDataMgr.GetSuccessCount()):
|
| | | ipyData = ipyDataMgr.GetSuccessByIndex(i)
|
| | | succID = ipyData.GetID()
|
| | | attrAwardDict = ipyData.GetAwardAttr()
|
| | | if not attrAwardDict:
|
| | | continue
|
| | | if not GetSuccHasGot(curPlayer, succID):
|
| | | continue
|
| | | for attrID, attrValue in attrAwardDict.items():
|
| | | attrDict[attrID] = attrDict.get(attrID, 0) + attrValue
|
| | | |
| | | #GameWorld.DebugLog(" 成就增加属性 attrDict=%s" % (attrDict)) |
| | | for attrID, attrValue in attrDict.items():
|
| | | PlayerControl.CalcAttrDict_Type(attrID, attrValue, allAttrList)
|
| | | |
| | | PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Success, allAttrList)
|
| | | return
|
| | |
|
| | | ## 刷新成就属性
|
| | | def RefreshSuccessAttr(curPlayer):
|
| | | CalcSuccessAttr(curPlayer)
|
| | | # 不立即刷新
|
| | | PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()
|
| | | return
|
| | |
|
| | | ## 同步成就信息
|
| | | # @param curPlayer: |
| | | # @param syncDict: 指定同步字典
|
| | | # @param isSendZero: 是否同步空数据(如连续类型进度值被清空时 or GM命令测试), 数据比较多,空数据默认就不同步了
|
| | | # @return
|
| | | def Sync_SuccessInfo(curPlayer, succIdList=[], isSendZero=False):
|
| | | succInfoListPack = ChPyNetSendPack.tagMCSuccessInfoList()
|
| | | succInfoListPack.Clear()
|
| | | succInfoListPack.SuccessInfoList = []
|
| | | if succIdList:
|
| | | syncIdList = succIdList
|
| | | else:
|
| | | syncIdList = []
|
| | | def SyncSuccessInfo(curPlayer, syncTypeCondList=None, isSendZero=False):
|
| | | if not syncTypeCondList:
|
| | | syncTypeCondList = []
|
| | | ipyDataMgr = IpyGameDataPY.IPY_Data()
|
| | | for i in xrange(ipyDataMgr.GetSuccessCount()):
|
| | | ipyData = ipyDataMgr.GetSuccessByIndex(i)
|
| | | succID = ipyData.GetID()
|
| | | syncIdList.append(succID)
|
| | | for index in range(ipyDataMgr.GetSuccessCount()):
|
| | | ipyData = ipyDataMgr.GetSuccessByIndex(index)
|
| | | # 已领取的不发 |
| | | if GetSuccHasGot(curPlayer, ipyData.GetSuccID()):
|
| | | continue
|
| | | succType = ipyData.GetSuccType()
|
| | | conds = ipyData.GetCondition()
|
| | | tcList = [succType, conds]
|
| | | if tcList in syncTypeCondList:
|
| | | continue
|
| | | syncTypeCondList.append(tcList)
|
| | |
|
| | | syncTypeDict = {}
|
| | | for succID in syncIdList:
|
| | | succData = GetSuccDataMng().GetSuccessData(succID)
|
| | | if not succData:
|
| | | continue
|
| | | succType = succData.succType
|
| | | condition = succData.condition
|
| | |
|
| | | CntValue = GetSuccFinishValue(curPlayer, succType, condition)
|
| | | isfinish = GetSuccIsFinish(curPlayer, succID)
|
| | | successInfoList = []
|
| | | objPoolMgr = ObjPool.GetPoolMgr()
|
| | | for succType, conds in syncTypeCondList:
|
| | | curValue = GetSuccValue(curPlayer, succType, conds)
|
| | | # 不发送为0的数据
|
| | | if not isSendZero and CntValue <= 0 and not isfinish:
|
| | | if not isSendZero and curValue <= 0:
|
| | | continue
|
| | | # 已领取的不发 |
| | | if GetSuccHasGot(curPlayer, succID):
|
| | | continue
|
| | | |
| | | if succType not in syncTypeDict:
|
| | | syncTypeDict[succType] = [[condition, CntValue]]
|
| | | elif [condition, CntValue] not in syncTypeDict[succType]:
|
| | | syncTypeDict[succType].append([condition, CntValue])
|
| | | succInfo = objPoolMgr.acquire(ChPyNetSendPack.tagSCSuccessInfo)
|
| | | succInfo.SuccType = succType
|
| | | succInfo.Conds = conds
|
| | | succInfo.CLen = len(succInfo.Conds)
|
| | | succInfo.CurValue = curValue
|
| | | successInfoList.append(succInfo)
|
| | |
|
| | | if not syncTypeDict:
|
| | | if not successInfoList:
|
| | | return
|
| | |
|
| | | for sType, conditionList in syncTypeDict.items():
|
| | | for condition, cntValue in conditionList:
|
| | | succInfo = ChPyNetSendPack.tagMCSuccessInfo()
|
| | | succInfo.Clear()
|
| | | succInfo.SuccType = sType
|
| | | succInfo.Condition = str(condition) if condition else '[0]'
|
| | | succInfo.Len = len(succInfo.Condition)
|
| | | succInfo.CntValue = cntValue
|
| | | succInfoListPack.SuccessInfoList.append(succInfo)
|
| | | |
| | | succInfoListPack.count = len(succInfoListPack.SuccessInfoList)
|
| | | NetPackCommon.SendFakePack(curPlayer, succInfoListPack)
|
| | | clientPack = objPoolMgr.acquire(ChPyNetSendPack.tagSCSuccessInfoList)
|
| | | clientPack.SuccessInfoList = successInfoList
|
| | | clientPack.Count = len(clientPack.SuccessInfoList)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | |
|
| | |
|
| | | ## 通知完成成就
|
| | | # @param None
|
| | | # @return
|
| | | def Notify_FinishSuccess(curPlayer, succID, finishTime):
|
| | | succFinishPack = ChPyNetSendPack.tagMCSuccessFinish()
|
| | | succFinishPack.Clear()
|
| | | succFinishPack.SuccID = succID
|
| | | #succFinishPack.FinishTime = finishTime |
| | | NetPackCommon.SendFakePack(curPlayer, succFinishPack)
|
| | | return
|
| | |
|
| | |
|
| | | def GetCanGetAwardSuccByType(curPlayer, successTypeList):
|
| | | ##根据类型获取可领取的成就
|
| | | succList = []
|
| | | for successType in successTypeList:
|
| | | succInfoList = GetSuccDataMng().GetSuccDataByType(successType)
|
| | | for succDataObj in succInfoList:
|
| | | succID = succDataObj.succID
|
| | | if GetSuccIsFinish(curPlayer, succID) and not GetSuccHasGot(curPlayer, succID):
|
| | | succList.append(succID)
|
| | | return succList
|
| | |
|
| | | def GiveSuccAward(curPlayer, succIDList, isGiveItem=True):
|
| | | #给成就奖励
|
| | | awardDict = {}
|
| | | for succID in succIDList:
|
| | | awardItemDict = __DoGetSuccTypeIndexAward(curPlayer, succID, isGiveItem)
|
| | | if not awardItemDict:
|
| | | continue
|
| | | for itemID,itemCnt in awardItemDict.items():
|
| | | awardDict[itemID] = awardDict.get(itemID, 0)+itemCnt
|
| | | return awardDict
|
| | |
|
| | | def GetSuccessPassportState(curPlayer):
|
| | | ## 成就通行证状态
|
| | | return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CTGGoodsBuyCount % ChConfig.Def_CTGID_SuccessPassport) > 0
|
| | |
|
| | | #// A5 42 领取成就奖励 #tagMCGetSuccessAward
|
| | | #
|
| | | #struct tagMCGetSuccessAward
|
| | | #{
|
| | | # tagHead Head;
|
| | | # DWORD SuccID; //成就ID
|
| | | # BYTE IsPassport; //是否通行证奖励
|
| | | #};
|
| | | def OnGetSuccessAward(index, clientData, tick):
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | succID = clientData.SuccID
|
| | | isPassport = clientData.IsPassport
|
| | | __DoGetSuccTypeIndexAward(curPlayer, succID, isPassport=isPassport)
|
| | | return
|
| | |
|
| | | ## 领取某个成就奖励
|
| | | # @param None
|
| | | # @return
|
| | | def __DoGetSuccTypeIndexAward(curPlayer, succID, isGiveItem=True, isPassport=False):
|
| | | GameWorld.DebugLog("领取成就奖励succID=%s,isPassport=%s" % (succID, isPassport))
|
| | | |
| | | succData = GetSuccDataMng().GetSuccessData(succID)
|
| | | if not succData:
|
| | | GameWorld.DebugLog(" 成就数据不存在!succID=%s" % (succID))
|
| | | return
|
| | | |
| | | if not succData.hasAward:
|
| | | GameWorld.DebugLog(" 该成就没有配置奖励!")
|
| | | return
|
| | | |
| | | finishTime = GetSuccIsFinish(curPlayer, succID)
|
| | | hasGot = GetSuccHasGot(curPlayer, succID) # 因为普通奖励领取后会重置是否已完成,所以如果已经领取普通奖励也代表已完成
|
| | | if finishTime <= 0 and not hasGot:
|
| | | GameWorld.DebugLog(" 该成就未完成!")
|
| | | return
|
| | | |
| | | if isPassport:
|
| | | if GetSuccPassportAwardHasGot(curPlayer, succID):
|
| | | GameWorld.DebugLog(" 该成就通行证奖励已经领取过!")
|
| | | return
|
| | | |
| | | if not GetSuccessPassportState(curPlayer):
|
| | | GameWorld.DebugLog(" 未开通成就通行证,无法领取通行证奖励!")
|
| | | return
|
| | | itemDict = succData.awardItemDict2
|
| | | if not itemDict:
|
| | | GameWorld.DebugLog(" 该成就没用通行证奖励!")
|
| | | return
|
| | | else:
|
| | | if hasGot:
|
| | | GameWorld.DebugLog(" 该成就奖励已经领取过!")
|
| | | return
|
| | | itemDict = succData.awardItemDict
|
| | | |
| | | # if awardItemDict and '[' in str(awardItemDict):
|
| | | # #修行成就奖励根据境界等级变
|
| | | # curRealmLV = curPlayer.GetOfficialRank()
|
| | | # sortLVList=sorted(awardItemDict.keys())
|
| | | # findLV = sortLVList[0]
|
| | | # for realmlv in sortLVList:
|
| | | # if curRealmLV <= int(realmlv):
|
| | | # findLV = realmlv
|
| | | # break
|
| | | # itemDict = dict(awardItemDict[findLV])
|
| | | # else:
|
| | | # itemDict = awardItemDict
|
| | | |
| | | # 检查背包
|
| | | if isGiveItem:
|
| | | if not ItemCommon.CheckPackEnough(curPlayer, itemDict):
|
| | | return
|
| | | # packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem)
|
| | | # needSpace = len(itemDict)
|
| | | # if needSpace > packSpace:
|
| | | # PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")
|
| | | # return
|
| | |
|
| | | # 更新领奖记录
|
| | | if isPassport:
|
| | | SetSuccPassportAwardHasGot(curPlayer, succID)
|
| | | else:
|
| | | SetSuccHasGot(curPlayer, succID)
|
| | | |
| | | # 给物品
|
| | | giveItemList = []
|
| | | if isGiveItem:
|
| | | for itemID, itemCnt in itemDict.items():
|
| | | isPutIn = ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, 0, [IPY_GameWorld.rptItem, IPY_GameWorld.rptAnyWhere])
|
| | | if isPutIn:
|
| | | giveItemList.append([itemID, itemCnt])
|
| | | |
| | | if isPassport:
|
| | | # 通行证奖励只给物品
|
| | | ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "SuccessAward")
|
| | | return itemDict
|
| | | |
| | | #给钱
|
| | | for moneyType, value in succData.moneyDict.items():
|
| | | PlayerControl.GiveMoney(curPlayer, int(moneyType), value)
|
| | | |
| | | #给经验
|
| | | if succData.exp:
|
| | | PlayerControl.PlayerControl(curPlayer).AddExp(succData.exp)
|
| | | #属性
|
| | | if succData.attrDict:
|
| | | RefreshSuccessAttr(curPlayer)
|
| | | #发红包
|
| | | if succData.redPacketID:
|
| | | PlayerFamilyRedPacket.CreatRedPacketByID(curPlayer, succData.redPacketID, PlayerFamilyRedPacket.State_NoGot, succID)
|
| | | #法宝经验
|
| | | if succData.magicWeaponExp:
|
| | | for mwID, addExp in succData.magicWeaponExp.items():
|
| | | PlayerMagicWeapon.AddMagicWeaponUpExp(curPlayer, mwID, addExp)
|
| | | EventReport.WriteEvent_MWSuccess(curPlayer, mwID, succID, ChConfig.CME_Log_End, 1)
|
| | | GameWorld.DebugLog(" OK! awardItemDict=%s moneyDict=%s" % (itemDict, succData.moneyDict))
|
| | | ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "SuccessAward", exp=succData.exp, moneyInfo=succData.moneyDict)
|
| | | return itemDict
|
| | |
|
| | |
|
| | |
|
| | | ## 通知成就对应奖励领奖记录
|
| | | # @param None
|
| | | # @return
|
| | | def Sync_SuccTypeIndexAwardRecord(curPlayer, succIDList=[], isSyncZero=False):
|
| | | def SyncSuccessAwardRecord(curPlayer, succIDList=[], isSyncZero=False):
|
| | | ## 通知成就对应奖励领奖记录
|
| | | if succIDList:
|
| | | recordIndexList = []
|
| | | for succID in succIDList:
|
| | |
| | | succCnt = ipyDataMgr.GetSuccessCount()
|
| | | if not succCnt:
|
| | | return
|
| | | maxSuccid = ipyDataMgr.GetSuccessByIndex(succCnt-1).GetID()
|
| | | recordIndexList = xrange(maxSuccid / 31+1)
|
| | | |
| | | succFARPack = ChPyNetSendPack.tagMCSuccessFinishAwardRecordList()
|
| | | succFARPack.Clear()
|
| | | succFARPack.RecordList = []
|
| | | maxSuccID = ipyDataMgr.GetSuccessByIndex(succCnt - 1).GetSuccID()
|
| | | recordIndexList = xrange(maxSuccID / 31 + 1)
|
| | | |
| | | objPoolMgr = ObjPool.GetPoolMgr()
|
| | | recordList = []
|
| | | for i in recordIndexList:
|
| | | awardRecord=curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Success_AwardRecord%i)
|
| | | passportAwardRecord=curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Success_PassportAward%i)
|
| | | if not isSyncZero and not awardRecord and not passportAwardRecord:
|
| | | awardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SuccessAward % i)
|
| | | if not isSyncZero and not awardRecord:
|
| | | continue
|
| | | recordInfo = ChPyNetSendPack.tagMCSuccessFinishAwardRecord()
|
| | | recordInfo = objPoolMgr.acquire(ChPyNetSendPack.tagSCSuccessAwardRecord)
|
| | | recordInfo.RecordIndex = i
|
| | | recordInfo.Record = awardRecord
|
| | | recordInfo.PassportRecord = passportAwardRecord
|
| | | succFARPack.RecordList.append(recordInfo)
|
| | | recordList.append(recordInfo)
|
| | |
|
| | | succFARPack.RecordCnt = len(succFARPack.RecordList)
|
| | | NetPackCommon.SendFakePack(curPlayer, succFARPack)
|
| | | return
|
| | |
|
| | |
|
| | | def AddEnterFBSuccess(curPlayer, mapID, addCount):
|
| | | #进入副本成就相关
|
| | | if not recordList:
|
| | | return
|
| | |
|
| | | if mapID == ChConfig.Def_FBMapID_BZZD:
|
| | | #仙界秘境
|
| | | DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_BZZD, addCount)
|
| | | elif mapID == ChConfig.Def_FBMapID_IceLode:
|
| | | #冰晶矿脉
|
| | | DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_IceLode, addCount)
|
| | | return
|
| | |
|
| | | def GetSuccessScoreAward(curPlayer, awardIndex):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | awardDict = IpyGameDataPY.GetFuncEvalCfg("SucceeScore", 1, {})
|
| | | if str(awardIndex) not in awardDict:
|
| | | return
|
| | | awardInfo = awardDict[str(awardIndex)]
|
| | | if len(awardInfo) != 2:
|
| | | return
|
| | | needScore, awardItemList = awardInfo
|
| | | if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_SuccessSocre, needScore):
|
| | | GameWorld.Log("成就积分不足,无法领奖! awardIndex=%s,needScore=%s" % (awardIndex, needScore), playerID)
|
| | | return
|
| | | awardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Success_ScoreAward)
|
| | | if awardState & pow(2, awardIndex):
|
| | | GameWorld.DebugLog("已领取过该成就积分奖励! awardIndex=%s" % awardIndex, playerID)
|
| | | return
|
| | | updAwardState = awardState | pow(2, awardIndex)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_Success_ScoreAward, updAwardState)
|
| | | GameWorld.DebugLog("领取成就积分奖励! awardIndex=%s,awardState=%s,updAwardState=%s" % (awardIndex, awardState, updAwardState), playerID)
|
| | | Sync_SuccessScoreAward(curPlayer)
|
| | | ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["SuccessScore", False, {}])
|
| | | return
|
| | |
|
| | | def Sync_SuccessScoreAward(curPlayer):
|
| | | clientPack = ChPyNetSendPack.tagMCSuccessScoreInfo()
|
| | | clientPack.Clear()
|
| | | clientPack.ScoreAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_Success_ScoreAward)
|
| | | clientPack = objPoolMgr.acquire(ChPyNetSendPack.tagSCSuccessAwardRecordList)
|
| | | clientPack.RecordList = recordList
|
| | | clientPack.RecordCnt = len(clientPack.RecordList)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | | |
| | | |