def __init__(self): self.__waitForSync = False self.__invalidateCbID = None self.__cache = defaultdict(dict) self.__personalMissionsHidden = {} self.__actionsCache = defaultdict(lambda: defaultdict(dict)) self.__actions2quests = {} self.__quests2actions = {} self.__questsDossierBonuses = defaultdict(set) self.__compensations = {} self.__personalMissions = PersonalMissionsCache() self.__questsProgressRequester = QuestsProgressRequester() self.__em = EventManager() self.__prefetcher = Prefetcher(self) self.onSyncStarted = Event(self.__em) self.onSyncCompleted = Event(self.__em) self.onProgressUpdated = Event(self.__em) self.onMissionVisited = Event(self.__em) self.onQuestConditionUpdated = Event(self.__em) self.onEventsVisited = Event(self.__em) self.onProfileVisited = Event(self.__em) self.onPersonalQuestsVisited = Event(self.__em) self.__lockedQuestIds = {} self.__dailyQuests = None return
class EventsCache(IEventsCache): USER_QUESTS = (EVENT_TYPE.BATTLE_QUEST, EVENT_TYPE.TOKEN_QUEST, EVENT_TYPE.PERSONAL_QUEST, EVENT_TYPE.PERSONAL_MISSION) SYSTEM_QUESTS = (EVENT_TYPE.REF_SYSTEM_QUEST,) lobbyContext = dependency.descriptor(ILobbyContext) rareAchievesCache = dependency.descriptor(IRaresCache) linkedSet = dependency.descriptor(ILinkedSetController) def __init__(self): self.__waitForSync = False self.__invalidateCbID = None self.__cache = defaultdict(dict) self.__personalMissionsHidden = {} self.__actionsCache = defaultdict(lambda : defaultdict(dict)) self.__actions2quests = {} self.__quests2actions = {} self.__questsDossierBonuses = defaultdict(set) self.__compensations = {} self.__personalMissions = PersonalMissionsCache() self.__questsProgress = QuestsProgressRequester() self.__em = EventManager() self.__prefetcher = Prefetcher(self) self.onSyncStarted = Event(self.__em) self.onSyncCompleted = Event(self.__em) self.onProgressUpdated = Event(self.__em) self.onMissionVisited = Event(self.__em) self.onEventsVisited = Event(self.__em) self.onProfileVisited = Event(self.__em) self.onPersonalQuestsVisited = Event(self.__em) self.__lockedQuestIds = {} return def init(self): self.__personalMissions.init() self.__prefetcher.init() def fini(self): self.__personalMissions.fini() self.__prefetcher.fini() self.__em.clear() self.__compensations.clear() self.__clearInvalidateCallback() def start(self): self.__lockedQuestIds = BigWorld.player().personalMissionsLock g_playerEvents.onPMLocksChanged += self.__onLockedQuestsChanged self.lobbyContext.getServerSettings().onServerSettingsChange += self.__onServerSettingsChange def stop(self): self.lobbyContext.getServerSettings().onServerSettingsChange -= self.__onServerSettingsChange g_playerEvents.onPMLocksChanged -= self.__onLockedQuestsChanged self.__clearCache() def clear(self): self.stop() quests_caches.clearNavInfo() @property def waitForSync(self): return self.__waitForSync @property def questsProgress(self): return self.__questsProgress def getPersonalMissions(self): return self.__personalMissions @property def prefetcher(self): return self.__prefetcher def getLockedQuestTypes(self, branch): questIDs = set() result = set() allQuests = self.getPersonalMissions().getQuestsForBranch(branch) for lockedList in self.__lockedQuestIds.values(): if lockedList is not None: questIDs.update(lockedList) for questID in questIDs: if questID in allQuests: result.add(allQuests[questID].getMajorTag()) return result @async @process def update(self, diff=None, callback=None): clearModifiersCache() yield self.getPersonalMissions().questsProgressRequest() if not self.getPersonalMissions().isQuestsProgressSynced(): callback(False) return else: yield self.__questsProgress.request() if not self.__questsProgress.isSynced(): callback(False) return isNeedToInvalidate = True isNeedToClearItemsCaches = False def _cbWrapper(*args): callback(*args) self.__personalMissions.update(self, diff) if diff is not None: isQPUpdated = 'quests' in diff or 'tokens' in diff isEventsDataUpdated = ('eventsData', '_r') in diff or diff.get('eventsData', {}) isNeedToInvalidate = isQPUpdated or isEventsDataUpdated hasVehicleUnlocks = False for intCD in diff.get('stats', {}).get('unlocks', set()): if getTypeOfCompactDescr(intCD) == GUI_ITEM_TYPE.VEHICLE: hasVehicleUnlocks = True break isNeedToClearItemsCaches = hasVehicleUnlocks or 'inventory' in diff and GUI_ITEM_TYPE.VEHICLE in diff['inventory'] if isNeedToInvalidate: self.__invalidateData(_cbWrapper) return if isNeedToClearItemsCaches: self.__clearQuestsItemsCache() _cbWrapper(True) return def getQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return not q.isHidden() and filterFunc(q) return self._getQuests(userFilterFunc) def getActiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return False if isLinkedSet(q.getGroupID()) and not self.linkedSet.isLinkedSetEnabled() else q.getFinishTimeLeft() and filterFunc(q) return self.getQuests(userFilterFunc) def getAdvisableQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): if q.getType() == EVENT_TYPE.MOTIVE_QUEST and not q.isAvailable().isValid: return False if q.getType() == EVENT_TYPE.TOKEN_QUEST and isMarathon(q.getID()): return False return False if isLinkedSet(q.getGroupID()) and not q.isAvailable().isValid else filterFunc(q) return self.getActiveQuests(userFilterFunc) def getMotiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.MOTIVE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getLinkedSetQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return isLinkedSet(q.getGroupID()) and filterFunc(q) return self.getQuests(userFilterFunc) def getBattleQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.BATTLE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getGroups(self, filterFunc=None): svrGroups = self._getQuestsGroups(filterFunc) svrGroups.update(self._getActionsGroups(filterFunc)) return svrGroups def getHiddenQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def hiddenFilterFunc(q): return q.isHidden() and filterFunc(q) return self._getQuests(hiddenFilterFunc) def getRankedQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def rankedFilterFunc(q): return q.getType() == EVENT_TYPE.RANKED_QUEST and filterFunc(q) return self._getQuests(rankedFilterFunc) def getAllQuests(self, filterFunc=None, includePersonalMissions=False): return self._getQuests(filterFunc, includePersonalMissions) def getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return filterFunc(q) and q.getType() != EVENT_TYPE.GROUP return self._getActions(userFilterFunc) def getActionEntities(self): return self.__getActionsEntitiesData() def getAnnouncedActions(self): return self.__getAnnouncedActions() def getEventBattles(self): battles = self.__getEventBattles() return EventBattles(battles.get('vehicleTags', set()), battles.get('vehicles', []), bool(battles.get('enabled', 0)), battles.get('arenaTypeID')) if battles else EventBattles(set(), [], 0, None) def isEventEnabled(self): return len(self.__getEventBattles()) > 0 and len(self.getEventVehicles()) > 0 @dependency.replace_none_kwargs(itemsCache=IItemsCache) def getEventVehicles(self, itemsCache=None): result = [] if itemsCache is None: return result else: for v in self.getEventBattles().vehicles: item = itemsCache.items.getItemByCD(v) if item.isInInventory: result.append(item) return sorted(result) def getEvents(self, filterFunc=None): svrEvents = self.getQuests(filterFunc) svrEvents.update(self.getActions(filterFunc)) return svrEvents def getCurrentEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() <= 0 < q.getFinishTimeLeft()) def getFutureEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() > 0) def getAffectedAction(self, item): actionEntities = self.getActionEntities() if actionEntities: entities = actionEntities[aei.ENTITIES_SECTION_NAME] actions = actionEntities[aei.ACTIONS_SECTION_NAME] steps = actionEntities[aei.STEPS_SECTION_NAME] if item in entities: entity = entities[item] actionNameIdx = entity[aei.ACTION_NAME_IDX] actionName = actions[actionNameIdx] stepNameIdx = entity[aei.ACTION_STEP_IDX] actionStep = steps[stepNameIdx] intersectedActions = entity[aei.AFFECTED_ACTIONS_IDX] return [actionName, actionStep, intersectedActions] return [] def getItemAction(self, item, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(15, []) for (key, value), actionID in values: if item.isPremium and key in ('creditsPrice', 'creditsPriceMultiplier') and not forCredits: continue result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get(itemTypeID, {}).get(intCD, tuple())) return result def getBoosterAction(self, booster, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING boosterID = booster.boosterID values = self.__actionsCache[ACTION_SECTION_TYPE.ALL_BOOSTERS][actionType].get(nations.NONE_INDEX, []) for (key, value), actionID in values: if forCredits and key == 'creditsPriceMultiplier': result.append((value, actionID)) if not forCredits and key == 'goldPriceMultiplier': result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.BOOSTER][actionType].get(boosterID, tuple())) return result def getRentAction(self, item, rentPackage): result = [] actionType = ACTION_MODIFIER_TYPE.RENT itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(15, []) for (_, value), actionID in values: result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get(itemTypeID, {}).get((intCD, rentPackage), tuple())) return result def getEconomicsAction(self, name): result = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get(name, []) resultMult = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get('%sMultiplier' % name, []) return tuple(result + resultMult) def isBalancedSquadEnabled(self): return bool(self.__getUnitRestrictions().get('enabled', False)) def getBalancedSquadBounds(self): return (self.__getUnitRestrictions().get('lowerBound', 0), self.__getUnitRestrictions().get('upperBound', 0)) def isSquadXpFactorsEnabled(self): return bool(self.__getUnitXpFactors().get('enabled', False)) def getSquadBonusLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithBonuses', ())) def getSquadPenaltyLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithPenalties', ())) def getSquadZeroBonuses(self): return set(self.__getUnitXpFactors().get('zeroBonusesFor', ())) def getQuestsDossierBonuses(self): return self.__questsDossierBonuses def getQuestsByTokenRequirement(self, token): result = [] for q in self._getQuests(includePersonalMissions=True).itervalues(): if token in [ t.getID() for t in q.accountReqs.getTokens() ]: result.append(q) return result def getQuestsByTokenBonus(self, token): result = [] for q in self._getQuests(includePersonalMissions=True).itervalues(): for t in q.getBonuses('tokens'): if token in t.getTokens().keys(): result.append(q) break return result def getCompensation(self, tokenID): return self.__compensations.get(tokenID) def hasQuestDelayedRewards(self, questID): return self.__questsProgress.hasQuestDelayedRewards(questID) def _getQuests(self, filterFunc=None, includePersonalMissions=False): result = {} groups = {} filterFunc = filterFunc or (lambda a: True) for qID, q in self.__getCommonQuestsIterator(): if qID in self.__quests2actions: q.linkedActions = self.__quests2actions[qID] if q.getType() == EVENT_TYPE.GROUP: groups[qID] = q continue if q.getFinishTimeLeft() <= 0: continue if not filterFunc(q): continue result[qID] = q if includePersonalMissions: for qID, q in self.getPersonalMissions().getAllQuests().iteritems(): if filterFunc(q): result[qID] = q for gID, group in groups.iteritems(): for qID in group.getGroupEvents(): if qID in result: result[qID].setGroupID(gID) children, parents, parentsName = self._makeQuestsRelations(result) for qID, q in result.iteritems(): if qID in children: q.setChildren(children[qID]) if qID in parents: q.setParents(parents[qID]) if qID in parentsName: q.setParentsName(parentsName[qID]) return result def _getQuestsGroups(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) result = {} for qID, q in self.__getCommonQuestsIterator(): if q.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(q): continue result[qID] = q return result def _getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) actions = self.__getActionsData() result = {} groups = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) actionID = a.getID() if actionID in self.__actions2quests: a.linkedQuests = self.__actions2quests[actionID] if a.getType() == EVENT_TYPE.GROUP: groups[actionID] = a continue if not filterFunc(a): continue result[actionID] = a for gID, group in groups.iteritems(): for aID in group.getGroupEvents(): if aID in result: result[aID].setGroupID(gID) return result def _getActionsGroups(self, filterFunc=None): actions = self.__getActionsData() filterFunc = filterFunc or (lambda a: True) result = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) if a.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(a): continue result[a.getID()] = a return result def _makeQuest(self, qID, qData, maker=_defaultQuestMaker, **kwargs): storage = self.__cache['quests'] if qID in storage: return storage[qID] q = storage[qID] = maker(qID, qData, self.__questsProgress) return q def _makeAction(self, aID, aData): storage = self.__cache['actions'] if aID in storage: return storage[aID] a = storage[aID] = createAction(aData.get('type', 0), aID, aData) return a @classmethod def _makeQuestsRelations(cls, quests): makeTokens = defaultdict(list) needTokens = defaultdict(list) for qID, q in quests.iteritems(): if q.getType() != EVENT_TYPE.GROUP: tokens = q.getBonuses('tokens') if tokens: for t in tokens[0].getTokens(): makeTokens[t].append(qID) for t in q.accountReqs.getTokens(): needTokens[qID].append(t.getID()) children = defaultdict(dict) for parentID, tokensIDs in needTokens.iteritems(): for tokenID in tokensIDs: children[parentID][tokenID] = makeTokens.get(tokenID, []) parents = defaultdict(lambda : defaultdict(list)) parentsName = defaultdict(lambda : defaultdict(list)) for parentID, tokens in children.iteritems(): for tokenID, chn in tokens.iteritems(): for childID in chn: parents[childID][tokenID].append(parentID) parentsName[childID][tokenID].append(quests[parentID].getUserName()) return (children, parents, parentsName) def __invalidateData(self, callback=lambda *args: None): self.__clearCache() self.__clearInvalidateCallback() self.__waitForSync = True self.onSyncStarted() for action in self.getActions().itervalues(): for modifier in action.getModifiers(): section = modifier.getSection() mType = modifier.getType() itemType = modifier.getItemType() values = modifier.getValues(action) currentSection = self.__actionsCache[section][mType] if itemType is not None: currentSection = currentSection.setdefault(itemType, {}) for k in values: if k in currentSection: currentSection[k] += values[k] currentSection[k] = values[k] rareAchieves = set() invalidateTimeLeft = sys.maxint for q in self.getCurrentEvents().itervalues(): dossierBonuses = q.getBonuses('dossier') if dossierBonuses: storage = self.__questsDossierBonuses[q.getID()] for bonus in dossierBonuses: records = bonus.getRecords() storage.update(set(bonus.getRecords().keys())) rareAchieves |= set((rId for r, rId in records.iteritems() if r[0] == ACHIEVEMENT_BLOCK.RARE)) timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is not None: isAvailable, errorMsg = q.isAvailable() if not isAvailable: if errorMsg in ('invalid_weekday', 'invalid_time_interval'): invalidateTimeLeft = min(invalidateTimeLeft, timeLeftInfo[0]) else: intervalBeginTimeLeft, (intervalStart, intervalEnd) = timeLeftInfo invalidateTimeLeft = min(invalidateTimeLeft, intervalBeginTimeLeft + intervalEnd - intervalStart) invalidateTimeLeft = min(invalidateTimeLeft, q.getFinishTimeLeft()) self.rareAchievesCache.request(rareAchieves) for q in self.getFutureEvents().itervalues(): timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is None: startTime = q.getStartTimeLeft() else: startTime = timeLeftInfo[0] invalidateTimeLeft = min(invalidateTimeLeft, startTime) if invalidateTimeLeft != sys.maxint: self.__loadInvalidateCallback(invalidateTimeLeft) self.__waitForSync = False self.__prefetcher.ask() self.__syncActionsWithQuests() self.__invalidateCompensations() self.onSyncCompleted() callback(True) return def __invalidateCompensations(self): self.__compensations.clear() for q in self.getHiddenQuests(lambda q: isMarathon(q.getGroupID())).itervalues(): self.__compensations.update(q.getCompensation()) def __clearQuestsItemsCache(self): for _, q in self._getQuests().iteritems(): q.accountReqs.clearItemsCache() q.vehicleReqs.clearItemsCache() def __syncActionsWithQuests(self): self.__actions2quests.clear() self.__quests2actions.clear() quests = self.__cache['quests'] actions = [ item for item in self.__cache['actions'] ] self.__actions2quests = {k:[] for k in actions} for questID, questData in quests.iteritems(): groupId = questData.getGroupID() linkedActionID = getLinkedActionID(groupId, actions) if linkedActionID is not None: self.__actions2quests[linkedActionID].append(questID) self.__convertQuests2actions() return def __convertQuests2actions(self): for action, quests in self.__actions2quests.iteritems(): for quest in quests: if quest in self.__quests2actions: self.__quests2actions[quest].append(action) self.__quests2actions[quest] = [action] @classmethod def __getEventsData(cls, eventsTypeName): try: if isPlayerAccount(): if eventsTypeName in BigWorld.player().eventsData: return pickle.loads(zlib.decompress(BigWorld.player().eventsData[eventsTypeName])) return {} LOG_DEBUG('Trying to get quests data from not account player', eventsTypeName, BigWorld.player()) except Exception: LOG_CURRENT_EXCEPTION() return {} def __getQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.QUEST) def __getPersonalQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.PERSONAL_QUEST) def __getActionsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION) def __getActionsEntitiesData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION_ENTITIES) def __getAnnouncedActions(self): return self.__getEventsData(EVENT_CLIENT_DATA.ANNOUNCED_ACTION_DATA) def __getIngameEventsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.INGAME_EVENTS) def __getEventBattles(self): return self.__getIngameEventsData().get('eventBattles', {}) def __getUnitRestrictions(self): return self.__getUnitData().get('restrictions', {}) def __getUnitXpFactors(self): return self.__getUnitData().get('xpFactors', {}) def __getUnitData(self): return self.__getEventsData(EVENT_CLIENT_DATA.SQUAD_BONUSES) def __getCommonQuestsIterator(self): questsData = self.__getQuestsData() questsData.update(self.__getPersonalQuestsData()) questsData.update(self.__getPersonalMissionsHiddenQuests()) for qID, qData in questsData.iteritems(): yield (qID, self._makeQuest(qID, qData)) motiveQuests = motivation_quests.g_cache.getAllQuests() or [] for questDescr in motiveQuests: yield (questDescr.questID, self._makeQuest(questDescr.questID, questDescr.questData, maker=_motiveQuestMaker)) def __loadInvalidateCallback(self, duration): LOG_DEBUG('load quest window invalidation callback (secs)', duration) self.__clearInvalidateCallback() self.__invalidateCbID = BigWorld.callback(math.ceil(duration), self.__invalidateData) def __clearInvalidateCallback(self): if self.__invalidateCbID is not None: BigWorld.cancelCallback(self.__invalidateCbID) self.__invalidateCbID = None return def __clearCache(self): self.__questsDossierBonuses.clear() self.__actionsCache.clear() for storage in self.__cache.itervalues(): storage.clear() clearModifiersCache() def __getPersonalMissionsHiddenQuests(self): if not self.__personalMissionsHidden: xmlPath = PERSONAL_MISSIONS_XML_PATH + '/tiles.xml' for quest in readQuestsFromFile(xmlPath, EVENT_TYPE.TOKEN_QUEST): self.__personalMissionsHidden[quest[0]] = quest[3] return self.__personalMissionsHidden.copy() def __onLockedQuestsChanged(self): self.__lockedQuestIds = BigWorld.player().personalMissionsLock def __onServerSettingsChange(self, *args, **kwargs): self.__personalMissions.updateDisabledStateForQuests()
class EventsCache(IEventsCache): USER_QUESTS = (EVENT_TYPE.BATTLE_QUEST, EVENT_TYPE.TOKEN_QUEST, EVENT_TYPE.PERSONAL_QUEST, EVENT_TYPE.PERSONAL_MISSION) lobbyContext = dependency.descriptor(ILobbyContext) rareAchievesCache = dependency.descriptor(IRaresCache) linkedSet = dependency.descriptor(ILinkedSetController) rankedController = dependency.descriptor(IRankedBattlesController) __epicController = dependency.descriptor(IEpicBattleMetaGameController) __battleRoyaleController = dependency.descriptor(IBattleRoyaleController) def __init__(self): self.__waitForSync = False self.__invalidateCbID = None self.__cache = defaultdict(dict) self.__personalMissionsHidden = {} self.__actionsCache = defaultdict(lambda: defaultdict(dict)) self.__actions2quests = {} self.__quests2actions = {} self.__questsDossierBonuses = defaultdict(set) self.__compensations = {} self.__personalMissions = PersonalMissionsCache() self.__questsProgressRequester = QuestsProgressRequester() self.__em = EventManager() self.__prefetcher = Prefetcher(self) self.onSyncStarted = Event(self.__em) self.onSyncCompleted = Event(self.__em) self.onProgressUpdated = Event(self.__em) self.onMissionVisited = Event(self.__em) self.onQuestConditionUpdated = Event(self.__em) self.onEventsVisited = Event(self.__em) self.onProfileVisited = Event(self.__em) self.onPersonalQuestsVisited = Event(self.__em) self.__lockedQuestIds = {} self.__dailyQuests = None return def init(self): self.__personalMissions.init() self.__prefetcher.init() def fini(self): self.__personalMissions.fini() self.__prefetcher.fini() self.__em.clear() self.__actions2quests.clear() self.__quests2actions.clear() self.__compensations.clear() self.__clearInvalidateCallback() def start(self): self.__onLockedQuestsChanged() self.__onDailyQuestsInfoChange() g_playerEvents.onPMLocksChanged += self.__onLockedQuestsChanged g_playerEvents.onDailyQuestsInfoChange += self.__onDailyQuestsInfoChange self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingsChange def stop(self, isDisconnected=False): if isDisconnected: self.__questsProgressRequester.clear() self.__dailyQuests = None self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingsChange g_playerEvents.onDailyQuestsInfoChange -= self.__onDailyQuestsInfoChange g_playerEvents.onPMLocksChanged -= self.__onLockedQuestsChanged self.__clearQuestsItemsCache() self.__actions2quests.clear() self.__quests2actions.clear() self.__compensations.clear() self.__clearCache() self.__clearInvalidateCallback() return def clear(self): self.stop(isDisconnected=True) quests_caches.clearNavInfo() @property def waitForSync(self): return self.__waitForSync @property def questsProgress(self): return self.__questsProgressRequester def getPersonalMissions(self): return self.__personalMissions @property def prefetcher(self): return self.__prefetcher @property def dailyQuests(self): return self.__dailyQuests def getLockedQuestTypes(self, branch): questIDs = set() result = set() allQuests = self.getPersonalMissions().getQuestsForBranch(branch) for lockedList in self.__lockedQuestIds.values(): if lockedList is not None: questIDs.update(lockedList) for questID in questIDs: if questID in allQuests: result.add(allQuests[questID].getMajorTag()) return result @async @process def update(self, diff=None, callback=None): clearModifiersCache() yield self.getPersonalMissions().questsProgressRequest() if not self.getPersonalMissions().isQuestsProgressSynced(): callback(False) return else: yield self.__questsProgressRequester.request() if not self.__questsProgressRequester.isSynced(): callback(False) return isNeedToInvalidate = True isNeedToClearItemsCaches = False isQPUpdated = False isQuestConditionUpdated = False def _cbWrapper(*args): callback(*args) self.__personalMissions.update(self, diff) if diff is not None: tokenIDs = sorted(diff.get('tokens', {}).keys()) if len(tokenIDs) % 2 == 0: if tokenIDs: isQuestConditionUpdated = True for idx, tokenID in enumerate(tokenIDs[::2]): validator = first([ validator for prefix, validator in UPDATABLE_CONDITION_TOKEN_TO_VALIDATOR.items() if tokenID.startswith(prefix) ]) if not validator or not validator( tokenID, tokenIDs[idx * 2 + 1]): isQuestConditionUpdated = False break isQPUpdated = 'quests' in diff or 'potapovQuests' in diff or 'pm2_progress' in diff if not isQPUpdated and 'tokens' in diff and not isQuestConditionUpdated: for tokenID in diff['tokens'].iterkeys(): if all((not tokenID.startswith(t) for t in NOT_FOR_PERSONAL_MISSIONS_TOKENS)): isQPUpdated = True break isEventsDataUpdated = ('eventsData', '_r') in diff or diff.get( 'eventsData', {}) isNeedToInvalidate = isQPUpdated or isEventsDataUpdated hasVehicleUnlocks = False for intCD in diff.get('stats', {}).get('unlocks', set()): if getTypeOfCompactDescr(intCD) == GUI_ITEM_TYPE.VEHICLE: hasVehicleUnlocks = True break isNeedToClearItemsCaches = hasVehicleUnlocks or 'inventory' in diff and GUI_ITEM_TYPE.VEHICLE in diff[ 'inventory'] if isNeedToInvalidate: self.__invalidateData(_cbWrapper) else: if isNeedToClearItemsCaches: self.__clearQuestsItemsCache() if isQuestConditionUpdated: self.onQuestConditionUpdated() if isQPUpdated: _cbWrapper(True) else: callback(True) return def getQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return not q.isHidden() and filterFunc(q) return self._getQuests(userFilterFunc) def getActiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) isPremiumQuestsEnable = self.lobbyContext.getServerSettings( ).getPremQuestsConfig().get('enabled', False) def userFilterFunc(q): if isLinkedSet(q.getGroupID() ) and not self.linkedSet.isLinkedSetEnabled(): return False return False if not isPremiumQuestsEnable and isPremium( q.getGroupID()) else q.getFinishTimeLeft() and filterFunc(q) return self.getQuests(userFilterFunc) def getAdvisableQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) isRankedSeasonOff = self.rankedController.getCurrentSeason() is None isEpicBattleEnabled = self.__epicController.isEnabled() def userFilterFunc(q): qGroup = q.getGroupID() qIsValid = q.isAvailable().isValid qID = q.getID() if q.getType() == EVENT_TYPE.MOTIVE_QUEST and not qIsValid: return False if q.getType() == EVENT_TYPE.TOKEN_QUEST and isMarathon(qID): return False if isLinkedSet(qGroup) or isPremium(qGroup) and not qIsValid: return False if not isEpicBattleEnabled and isDailyEpic(qGroup): return False if isBattleRoyale(qGroup): quests = self.__battleRoyaleController.getQuests() if qID not in quests: return False if isMapsTraining(qGroup): return q.shouldBeShown() return False if isRankedSeasonOff and ( isRankedDaily(qGroup) or isRankedPlatform(qGroup)) else filterFunc(q) return self.getActiveQuests(userFilterFunc) def getMotiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.MOTIVE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getLinkedSetQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return isLinkedSet(q.getGroupID()) and filterFunc(q) return self.getQuests(userFilterFunc) def getPremiumQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return isPremium(q.getGroupID()) and filterFunc(q) return self.getQuests(userFilterFunc) def getDailyQuests(self, filterFunc=None, includeEpic=False): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return False if not includeEpic and q.getType( ) == EVENT_TYPE.TOKEN_QUEST else filterFunc(q) return self._getDailyQuests(userFilterFunc) def getDailyEpicQuest(self): dailyQuests = self._getDailyQuests() for q in dailyQuests.values(): if q.getType() == EVENT_TYPE.TOKEN_QUEST and not q.isCompleted(): return q def getBattleQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.BATTLE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getCelebrityQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return isCelebrityQuest(q.getID()) and filterFunc(q) return self.getAllQuests(userFilterFunc, includeCelebrityQuests=True) def getGroups(self, filterFunc=None): svrGroups = self._getQuestsGroups(filterFunc) svrGroups.update(self._getActionsGroups(filterFunc)) return svrGroups def getHiddenQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def hiddenFilterFunc(q): return q.isHidden() and filterFunc(q) return self._getQuests(hiddenFilterFunc) def getRankedQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def rankedFilterFunc(q): return q.getType() == EVENT_TYPE.RANKED_QUEST and filterFunc(q) return self._getQuests(rankedFilterFunc) def getAllQuests(self, filterFunc=None, includePersonalMissions=False, includeCelebrityQuests=False): return self._getQuests(filterFunc, includePersonalMissions, includeCelebrityQuests) def getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return filterFunc(q) and q.getType() != EVENT_TYPE.GROUP return self._getActions(userFilterFunc) def getActionEntities(self): return self.__getActionsEntitiesData() def getAnnouncedActions(self): return self.__getAnnouncedActions() def getQuestByID(self, qID): quest = self._getCachedQuest(qID) if quest is not None: return quest else: questsData = self.__getQuestsData() questsData.update(self.__getPersonalQuestsData()) questsData.update(self.__getPersonalMissionsHiddenQuests()) return self._makeQuest( qID, questsData[qID]) if qID in questsData else None def getQuestsByIDs(self, qIDs): result = {} data = {} for qID in qIDs: quest = self._getCachedQuest(qID) if quest is not None: result[qID] = quest if not data: data = self.__getQuestsData() data.update(self.__getPersonalQuestsData()) data.update(self.__getPersonalMissionsHiddenQuests()) if qID in data: result[qID] = self._makeQuest(qID, data[qID]) result[qID] = None return result def getEvents(self, filterFunc=None): svrEvents = self.getQuests(filterFunc) svrEvents.update(self.getActions(filterFunc)) return svrEvents def getCurrentEvents(self): return self.getEvents( lambda q: q.getStartTimeLeft() <= 0 < q.getFinishTimeLeft()) def getFutureEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() > 0) def getAffectedAction(self, item): actionEntities = self.getActionEntities() if actionEntities: entities = actionEntities[aei.ENTITIES_SECTION_NAME] actions = actionEntities[aei.ACTIONS_SECTION_NAME] steps = actionEntities[aei.STEPS_SECTION_NAME] if item in entities: entity = entities[item] actionNameIdx = entity[aei.ACTION_NAME_IDX] actionName = actions[actionNameIdx] stepNameIdx = entity[aei.ACTION_STEP_IDX] actionStep = steps[stepNameIdx] intersectedActions = entity[aei.AFFECTED_ACTIONS_IDX] return [actionName, actionStep, intersectedActions] return [] def getItemAction(self, item, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get( itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get( itemTypeID, {}).get(15, []) for (_, value), actionID in values: if item.isPremium and value in ( 'creditsPrice', 'creditsPriceMultiplier') and not forCredits: continue result.append((value, actionID)) result.extend( self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get( itemTypeID, {}).get(intCD, tuple())) return result def getBoosterAction(self, booster, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING boosterID = booster.boosterID values = self.__actionsCache[ ACTION_SECTION_TYPE.ALL_BOOSTERS][actionType].get( nations.NONE_INDEX, []) for (key, value), actionID in values: if forCredits and key == 'creditsPriceMultiplier': result.append((value, actionID)) if not forCredits and key == 'goldPriceMultiplier': result.append((value, actionID)) result.extend( self.__actionsCache[ACTION_SECTION_TYPE.BOOSTER][actionType].get( boosterID, tuple())) return result def getRentAction(self, item, rentPackage): result = [] actionType = ACTION_MODIFIER_TYPE.RENT itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get( itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get( itemTypeID, {}).get(15, []) for (_, value), actionID in values: result.append((value, actionID)) result.extend( self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get( itemTypeID, {}).get((intCD, rentPackage), tuple())) return result def getEconomicsAction(self, name): result = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ ACTION_MODIFIER_TYPE.DISCOUNT].get(name, []) resultMult = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ ACTION_MODIFIER_TYPE.DISCOUNT].get('%sMultiplier' % name, []) return tuple(result + resultMult) def getHeroTankAdventCalendarRedirectAction(self): isEnabled = False start, finish = (0, 0) def containsHeroToAdvent(a): return any((step.get('name') == 'HeroTankAdventCalendarRedirect' for step in a.getData().get('steps', []))) action = first(self.getActions(containsHeroToAdvent).values()) if action is not None: start = action.getStartTimeRaw() finish = action.getFinishTimeRaw() isEnabled = any((m.getIsEnabled() for m in action.getModifiers())) return {'isEnabled': isEnabled, 'start': start, 'finish': finish} def getTradeInActions(self): def containsTradeIn(a): return any((step.get('name') == 'set_TradeInParams' for step in a.getData().get('steps', []))) return self.getActions(containsTradeIn).values() def isBalancedSquadEnabled(self): return bool(self.__getUnitRestrictions().get('enabled', False)) def getBalancedSquadBounds(self): return (self.__getUnitRestrictions().get('lowerBound', 0), self.__getUnitRestrictions().get('upperBound', 0)) def isSquadXpFactorsEnabled(self): return bool(self.__getUnitXpFactors().get('enabled', False)) def getSquadBonusLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithBonuses', ())) def getSquadPenaltyLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithPenalties', ())) def getSquadZeroBonuses(self): return set(self.__getUnitXpFactors().get('zeroBonusesFor', ())) def getSquadXPFactor(self): return self.__getUnitXpFactors().get('factor', 0) def getQuestsDossierBonuses(self): return self.__questsDossierBonuses def getQuestsByTokenRequirement(self, token): result = [] for q in self._getQuests(includePersonalMissions=False).itervalues(): if token in [t.getID() for t in q.accountReqs.getTokens()]: result.append(q) return result def getQuestsByTokenBonus(self, token): result = [] for q in self._getQuests(includePersonalMissions=True).itervalues(): for t in q.getBonuses('tokens'): if token in t.getTokens().keys(): result.append(q) break return result def getCompensation(self, tokenID): return self.__compensations.get(tokenID) def hasQuestDelayedRewards(self, questID): return self.__questsProgressRequester.hasQuestDelayedRewards(questID) def getProgressiveReward(self): progressiveConfig = self.lobbyContext.getServerSettings( ).getProgressiveRewardConfig() if not progressiveConfig.isEnabled: return None else: maxSteps = progressiveConfig.maxLevel currentStep = self.questsProgress.getTokenCount( progressiveConfig.levelTokenID) probability = self.questsProgress.getTokenCount( progressiveConfig.probabilityTokenID) / 100 return _ProgressiveReward(currentStep, probability, maxSteps) def _getDailyQuests(self, filterFunc=None): result = {} filterFunc = filterFunc or (lambda a: True) for qID, q in self.__getDailyQuestsIterator(): if filterFunc(q): result[qID] = q return result def getLobbyHeaderTabCounter(self): counterValue = None alias = None def containsLobbyHeaderTabCounter(a): return any((step.get('name') == 'LobbyHeaderTabCounterModification' for step in a.getData().get('steps', []))) action = first(self.getActions(containsLobbyHeaderTabCounter).values()) if action is not None: counterValue = first( (m.getCounterValue() for m in action.getModifiers())) alias = first((m.getAlias() for m in action.getModifiers())) return (alias, counterValue) def _getQuests(self, filterFunc=None, includePersonalMissions=False, includeCelebrityQuests=False): result = {} groups = {} filterFunc = filterFunc or (lambda a: True) for qID, q in self.__getCommonQuestsIterator(): if not includeCelebrityQuests and isCelebrityQuest(qID): continue if qID in self.__quests2actions: q.linkedActions = self.__quests2actions[qID] if q.getType() == EVENT_TYPE.GROUP: groups[qID] = q continue if q.getFinishTimeLeft() <= 0: continue if not filterFunc(q): continue result[qID] = q if includePersonalMissions: for qID, q in self.getPersonalMissions().getAllQuests().iteritems( ): if filterFunc(q): result[qID] = q for gID, group in groups.iteritems(): for qID in group.getGroupEvents(): if qID in result: result[qID].setGroupID(gID) children, parents, parentsName = self._makeQuestsRelations(result) for qID, q in result.iteritems(): if qID in children: q.setChildren(children[qID]) if qID in parents: q.setParents(parents[qID]) if qID in parentsName: q.setParentsName(parentsName[qID]) return result def _getQuestsGroups(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) result = {} for qID, q in self.__getCommonQuestsIterator(): if q.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(q): continue result[qID] = q return result def _getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) actions = self.__getActionsData() result = {} groups = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) actionID = a.getID() if actionID in self.__actions2quests: a.linkedQuests = self.__actions2quests[actionID] if a.getType() == EVENT_TYPE.GROUP: groups[actionID] = a continue if not filterFunc(a): continue result[actionID] = a for gID, group in groups.iteritems(): for aID in group.getGroupEvents(): if aID in result: result[aID].setGroupID(gID) return result def _getActionsGroups(self, filterFunc=None): actions = self.__getActionsData() filterFunc = filterFunc or (lambda a: True) result = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) if a.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(a): continue result[a.getID()] = a return result def _getCachedQuest(self, qID): storage = self.__cache['quests'] return storage[qID] if qID in storage else None def _makeQuest(self, qID, qData, maker=_defaultQuestMaker, **kwargs): storage = self.__cache['quests'] if qID in storage: return storage[qID] q = storage[qID] = maker(qID, qData, self.__questsProgressRequester) return q def _makeAction(self, aID, aData): storage = self.__cache['actions'] if aID in storage: return storage[aID] a = storage[aID] = createAction(aData.get('type', 0), aID, aData) return a @classmethod def _makeQuestsRelations(cls, quests): makeTokens = defaultdict(list) needTokens = defaultdict(list) for qID, q in quests.iteritems(): if q.getType() not in (EVENT_TYPE.GROUP, EVENT_TYPE.PERSONAL_MISSION): for tokenBonus in q.getBonuses('tokens'): for t in tokenBonus.getTokens(): makeTokens[t].append(qID) for t in q.accountReqs.getTokens(): needTokens[qID].append(t.getID()) children = defaultdict(dict) for parentID, tokensIDs in needTokens.iteritems(): for tokenID in tokensIDs: children[parentID][tokenID] = makeTokens.get(tokenID, []) parents = defaultdict(lambda: defaultdict(list)) parentsName = defaultdict(lambda: defaultdict(list)) for parentID, tokens in children.iteritems(): for tokenID, chn in tokens.iteritems(): for childID in chn: parents[childID][tokenID].append(parentID) parentsName[childID][tokenID].append( quests[parentID].getUserName()) return (children, parents, parentsName) def __invalidateData(self, callback=lambda *args: None): self.__clearCache() self.__clearInvalidateCallback() self.__waitForSync = True self.onSyncStarted() for action in self.getActions().itervalues(): for modifier in action.getModifiers(): section = modifier.getSection() mType = modifier.getType() itemType = modifier.getItemType() values = modifier.getValues(action) currentSection = self.__actionsCache[section][mType] if itemType is not None: currentSection = currentSection.setdefault(itemType, {}) for k in values: if k in currentSection: currentSection[k] += values[k] currentSection[k] = values[k] rareAchieves = set() invalidateTimeLeft = sys.maxint for q in self.getCurrentEvents().itervalues(): dossierBonuses = q.getBonuses('dossier') if dossierBonuses: storage = self.__questsDossierBonuses[q.getID()] for bonus in dossierBonuses: records = bonus.getRecords() storage.update(set(bonus.getRecords().keys())) rareAchieves |= set((rId for r, rId in records.iteritems() if r[0] == ACHIEVEMENT_BLOCK.RARE)) timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is not None: isAvailable, errorMsg = q.isAvailable() if not isAvailable: if errorMsg in ('invalid_weekday', 'invalid_time_interval'): invalidateTimeLeft = min(invalidateTimeLeft, timeLeftInfo[0]) else: intervalBeginTimeLeft, (intervalStart, intervalEnd) = timeLeftInfo invalidateTimeLeft = min( invalidateTimeLeft, intervalBeginTimeLeft + intervalEnd - intervalStart) invalidateTimeLeft = min(invalidateTimeLeft, q.getFinishTimeLeft()) self.rareAchievesCache.request(rareAchieves) for q in self.getFutureEvents().itervalues(): timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is None: startTime = q.getStartTimeLeft() else: startTime = timeLeftInfo[0] invalidateTimeLeft = min(invalidateTimeLeft, startTime) if invalidateTimeLeft != sys.maxint: self.__loadInvalidateCallback(invalidateTimeLeft) self.__waitForSync = False self.__prefetcher.ask() self.__syncActionsWithQuests() self.__invalidateCompensations() self.onSyncCompleted() callback(True) return def __invalidateCompensations(self): self.__compensations.clear() for q in self.getHiddenQuests( lambda q: isMarathon(q.getGroupID())).itervalues(): self.__compensations.update(q.getCompensation()) def __clearQuestsItemsCache(self): for _, q in self._getQuests().iteritems(): q.accountReqs.clearItemsCache() q.vehicleReqs.clearItemsCache() def __syncActionsWithQuests(self): self.__actions2quests.clear() self.__quests2actions.clear() quests = self.__cache['quests'] actions = [item for item in self.__cache['actions']] self.__actions2quests = {k: [] for k in actions} for questID, questData in quests.iteritems(): groupId = questData.getGroupID() linkedActionID = getLinkedActionID(groupId, actions) if linkedActionID is not None: self.__actions2quests[linkedActionID].append(questID) self.__convertQuests2actions() return def __convertQuests2actions(self): for action, quests in self.__actions2quests.iteritems(): for quest in quests: if quest in self.__quests2actions: self.__quests2actions[quest].append(action) self.__quests2actions[quest] = [action] @classmethod def __getEventsData(cls, eventsTypeName): return getEventsData(eventsTypeName) def __getQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.QUEST) def __getPersonalQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.PERSONAL_QUEST) def __getDailyQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.DAILY_QUESTS) def __getActionsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION) def __getActionsEntitiesData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION_ENTITIES) def __getAnnouncedActions(self): return self.__getEventsData(EVENT_CLIENT_DATA.ANNOUNCED_ACTION_DATA) def __getUnitRestrictions(self): return self.__getUnitData().get('restrictions', {}) def __getUnitXpFactors(self): return self.__getUnitData().get('xpFactors', {}) def __getUnitData(self): return self.__getEventsData(EVENT_CLIENT_DATA.SQUAD_BONUSES) def __getDailyQuestsIterator(self): for qID, qData in self.__getDailyQuestsData().iteritems(): yield (qID, self._makeQuest(qID, qData)) def __getCommonQuestsIterator(self): questsData = self.__getQuestsData() questsData.update(self.__getPersonalQuestsData()) questsData.update(self.__getPersonalMissionsHiddenQuests()) questsData.update(self.__getDailyQuestsData()) for qID, qData in questsData.iteritems(): yield (qID, self._makeQuest(qID, qData)) motiveQuests = motivation_quests.g_cache.getAllQuests() or [] for questDescr in motiveQuests: yield (questDescr.questID, self._makeQuest(questDescr.questID, questDescr.questData, maker=_motiveQuestMaker)) def __loadInvalidateCallback(self, duration): LOG_DEBUG('load quest window invalidation callback (secs)', duration) self.__clearInvalidateCallback() self.__invalidateCbID = BigWorld.callback( math.ceil(duration), self.__onInvalidateNearestQuests) def __onInvalidateNearestQuests(self): if BigWorld.player() is not None: self.__invalidateData() return def __clearInvalidateCallback(self): if self.__invalidateCbID is not None: BigWorld.cancelCallback(self.__invalidateCbID) self.__invalidateCbID = None return def __clearCache(self): self.__questsDossierBonuses.clear() self.__actionsCache.clear() for storage in self.__cache.itervalues(): storage.clear() clearModifiersCache() def __getPersonalMissionsHiddenQuests(self): if not self.__personalMissionsHidden: xmlPath = PERSONAL_MISSIONS_XML_PATH + '/tiles.xml' for quest in readQuestsFromFile(xmlPath, EVENT_TYPE.TOKEN_QUEST): self.__personalMissionsHidden[quest[0]] = quest[3] return self.__personalMissionsHidden.copy() def __onLockedQuestsChanged(self): self.__lockedQuestIds = BigWorld.player().personalMissionsLock def __onDailyQuestsInfoChange(self): self.__dailyQuests = _DailyQuestsData(**BigWorld.player().dailyQuests) def __onServerSettingsChange(self, *args, **kwargs): self.__personalMissions.updateDisabledStateForQuests()