class LootBoxNotification(object): _settingsCore = dependency.descriptor(ISettingsCore) _itemsCache = dependency.descriptor(IItemsCache) _temp_storage = defaultdict(dict) @classmethod def hasNewBox(cls, boxType, category=''): count = cls.__getInventoryCount(boxType, category) settingsCount = cls.__getNewCount(boxType, category) return count > settingsCount @classmethod def hasDeliveredBox(cls, category): count = cls.__getInventoryCount(NewYearLootBoxes.PREMIUM, category) settingsCount = cls.__getCategoryDeliveredCount(category) return count > settingsCount @classmethod def setCategoryNewCount(cls, boxType, category=''): count = cls.__getInventoryCount(boxType, category) cls.__setCategoryNewCount(boxType, category, count) @classmethod def setCategoryDeliveredCount(cls, category): count = cls.__getInventoryCount(NewYearLootBoxes.PREMIUM, category) cls.__setCategoryDeliveredCount(category, count) @classmethod def setTotalLootBoxesCount(cls, count): cls._temp_storage[SETTINGS_SECTIONS.LOOT_BOX_VIEWED]['count'] = count @classmethod def saveSettings(cls): for section, settings in cls._temp_storage.iteritems(): cls._settingsCore.serverSettings.setSectionSettings( section, settings) cls.__resetTempStorage() @classmethod def __resetTempStorage(cls): cls._temp_storage.clear() @classmethod def __getInventoryCount(cls, boxType, category=''): count = 0 for lootBox in cls._itemsCache.items.tokens.getLootBoxes().itervalues( ): if lootBox.getCategory() == category and lootBox.getType( ) == boxType: count += lootBox.getInventoryCount() return count @classmethod def __getNewCount(cls, boxType, category=''): if boxType == NewYearLootBoxes.PREMIUM: return cls.__getCategorySettingCount( category, NYLootBoxesStorageKeys.NEW_COUNT) return cls.__getCategorySettingCount( NewYearLootBoxes.COMMON, NYLootBoxesStorageKeys.NEW_COUNT ) if boxType == NewYearLootBoxes.COMMON else None @classmethod def __getCategoryDeliveredCount(cls, category): return cls.__getCategorySettingCount( category, NYLootBoxesStorageKeys.DELIVERED_COUNT) @classmethod def __getCategorySettingCount(cls, category, settingKey): settingName = _SETTINGS_MAP.get(category) if settingName is None: _logger.error( 'Failed to get serverSettings: [%s] for lootboxes category: [%s]', settingKey, category) return 0 else: categorySettings = cls._temp_storage[settingName] if settingKey not in categorySettings: count = cls._settingsCore.serverSettings.getSectionSettings( settingName, settingKey, 0) categorySettings[settingKey] = count return cls._temp_storage[settingName][settingKey] @classmethod def __setCategoryNewCount(cls, boxType, category, count): if boxType == NewYearLootBoxes.PREMIUM: cls.__setCategorySettingCount(category, NYLootBoxesStorageKeys.NEW_COUNT, count) elif boxType == NewYearLootBoxes.COMMON: cls.__setCategorySettingCount(NewYearLootBoxes.COMMON, NYLootBoxesStorageKeys.NEW_COUNT, count) @classmethod def __setCategoryDeliveredCount(cls, category, count): cls.__setCategorySettingCount(category, NYLootBoxesStorageKeys.DELIVERED_COUNT, count) @classmethod def __setCategorySettingCount(cls, category, settingKey, count): settingName = _SETTINGS_MAP.get(category) if settingName is not None: cls._temp_storage[settingName][settingKey] = count else: _logger.error( 'Failed to set serverSettings: [%s] for lootboxes category: [%s]', settingKey, category) return
class VehicleModulesWindow(VehicleModulesWindowMeta): comparisonBasket = dependency.descriptor(IVehicleComparisonBasket) def __init__(self, ctx=None): super(VehicleModulesWindow, self).__init__() self.__vehIntCD = ctx['vehCD'] self.__vehIndex = ctx['index'] self.__nodes = None self.__vehicle = None self.__nodeDataGenerator = None self.__currentModulesType = None return def _populate(self): super(VehicleModulesWindow, self)._populate() basketVehicle = self.comparisonBasket.getVehicleAt(self.__vehIndex) self.__initialize(basketVehicle.getVehicleStrCD(), basketVehicle.getModulesType()) self.as_setAttentionVisibleS(basketVehicle.isInInventory() and not basketVehicle.isActualModules()) stockVehicle = Vehicle(basketVehicle.getStockVehStrCD()) self.__modulesInstaller = _ModulesInstaller( getInstalledModulesCDs(stockVehicle)) self.comparisonBasket.onSwitchChange += self.onWindowClose self.as_setInitDataS({ 'windowTitle': _ms(VEH_COMPARE.MODULESVIEW_WINDOWTITLE, vehName=stockVehicle.userName), 'description': text_styles.main(_ms(VEH_COMPARE.MODULESVIEW_DESCRIPTION)), 'resetBtnLabel': VEH_COMPARE.MODULESVIEW_RESETBTNLABEL, 'closeBtnLabel': VEH_COMPARE.MODULESVIEW_CLOSEBTNLABEL, 'compareBtnLabel': VEH_COMPARE.MODULESVIEW_COMPAREBTNLABEL, 'resetBtnTooltip': VEH_COMPARE.MODULESVIEW_RESETBTNLABEL_TOOLTIP, 'closeBtnTooltip': VEH_COMPARE.MODULESVIEW_CLOSEBTNLABEL_TOOLTIP, 'compareBtnTooltip': VEH_COMPARE.MODULESVIEW_COMPAREBTNLABEL_TOOLTIP }) def _dispose(self): self.comparisonBasket.onSwitchChange -= self.onWindowClose self.__vehicle = None self.__modulesInstaller.dispose() self.__modulesInstaller = None if self.__nodeDataGenerator: self.__nodeDataGenerator.clear(True) self.__nodeDataGenerator = None super(VehicleModulesWindow, self)._dispose() return def onWindowClose(self): self.destroy() def onResetBtnBtnClick(self): def __logModuleWarning(): LOG_WARNING( 'Unable to apply the following modules type: {}'.format( self.__currentModulesType)) def __logModuleError(): LOG_ERROR('Attempt to apply unsupported modules type: {}'.format( self.__currentModulesType)) basketVehicle = self.comparisonBasket.getVehicleAt(self.__vehIndex) if basketVehicle.isInInventory(): if self.__currentModulesType == MODULES_TYPES.CUSTOM or self.__currentModulesType == MODULES_TYPES.BASIC: self.__initialize(basketVehicle.getInvVehStrCD(), MODULES_TYPES.CURRENT) elif self.__currentModulesType == MODULES_TYPES.CURRENT: __logModuleWarning() else: __logModuleError() elif self.__currentModulesType == MODULES_TYPES.CUSTOM: self.__initialize(basketVehicle.getStockVehStrCD(), MODULES_TYPES.BASIC) elif self.__currentModulesType == MODULES_TYPES.BASIC: __logModuleWarning() else: __logModuleError() def onCompareBtnClick(self): self.comparisonBasket.applyModulesFromVehicle(self.__vehIndex, self.__vehicle) self.destroy() def onModuleHover(self, moduleId): moduleId = int(moduleId) if moduleId: allConflicted = self.__modulesInstaller.updateConflicted( moduleId, self.__vehicle) changedNodesStates = [] for modulesByType in allConflicted: for conflictedIntCD in modulesByType: for mData in self.__nodes: if mData['id'] == conflictedIntCD: mData['state'] |= NODE_STATE_FLAGS.DASHED changedNodesStates.append( (conflictedIntCD, mData['state'])) if changedNodesStates: self.as_setNodesStatesS(changedNodesStates) else: allConflicted = self.__modulesInstaller.getConflictedModules() if allConflicted: changedNodesStates = [] for modulesByType in allConflicted: for conflictedIntCD in modulesByType: for mData in self.__nodes: if mData['id'] == conflictedIntCD: mData['state'] &= ~NODE_STATE_FLAGS.DASHED changedNodesStates.append( (conflictedIntCD, mData['state'])) self.__modulesInstaller.clearConflictedModules() self.as_setNodesStatesS(changedNodesStates) @process def onModuleClick(self, moduleId): moduleId = int(moduleId) newComponentItem = _getModule(moduleId) isMainFit, mainReason = newComponentItem.mayInstall(self.__vehicle) if isMainFit: yield getPreviewInstallerProcessor(self.__vehicle, newComponentItem).request() conflictedModules = self.__modulesInstaller.getConflictedModules() if self.__modulesInstaller.hasConflicted(): for modulesByType in conflictedModules: for moduleCD in modulesByType: conflictedModule = _getModule(moduleCD) yield getPreviewInstallerProcessor( self.__vehicle, conflictedModule).request() if not isMainFit: yield getPreviewInstallerProcessor(self.__vehicle, newComponentItem).request() self.__updateChangedSlots() self.__updateModulesType( self.comparisonBasket.getVehicleAt(self.__vehIndex).getModulesType( strCD=self.__vehicle.descriptor.makeCompactDescr())) def __initialize(self, strCD, modulesType): self.__vehicle = Vehicle(strCD) if self.__nodeDataGenerator is not None: self.__nodeDataGenerator.setVehicle(vehicle=self.__vehicle) else: if USE_XML_DUMPING and IS_DEVELOPMENT: dumper = dumpers.ResearchItemsXMLDumper() else: dumper = dumpers.ResearchBaseDumper() self.__nodeDataGenerator = _PreviewItemsData( dumper, self.__vehicle) self.__updateModulesData() self.as_setItemS(AVAILABLE_NAMES[self.__vehicle.nationID], self.__nodes) self.__updateModulesType(modulesType) return def __updateChangedSlots(self): def __extractData(targetList): return dict( map(lambda moduleData: (moduleData['id'], moduleData['state']), targetList)) oldModulesData = __extractData(self.__nodes) self.__updateModulesData() newModulesData = __extractData(self.__nodes) changedSlots = [] for k, v in newModulesData.iteritems(): if v != oldModulesData[k]: changedSlots.append((k, v)) self.as_setNodesStatesS(changedSlots) def __updateModulesData(self): self.__nodeDataGenerator.load() dump = self.__nodeDataGenerator.dump() self.__nodes = dump['nodes'] def __updateModulesType(self, modulesType): self.__currentModulesType = modulesType basketVehicle = self.comparisonBasket.getVehicleAt(self.__vehIndex) if basketVehicle.isInInventory(): btnEnabled = modulesType != MODULES_TYPES.CURRENT else: btnEnabled = modulesType != MODULES_TYPES.BASIC self.as_setStateS(stateText=text_styles.neutral( _ms('#veh_compare:modulesView/moduleSet/{}'.format(modulesType))), stateEnabled=btnEnabled)
class InternalLinksHandler(IInternalLinksController): browserCtrl = dependency.descriptor(IBrowserController) def __init__(self): super(InternalLinksHandler, self).__init__() self.__urlMarcos = None self._browserID = None return def init(self): self.__urlMarcos = URLMarcos() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMarcos is not None: self.__urlMarcos.clear() self.__urlMarcos = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMarcos.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title='', browserSize=None, showActionBtn=True, showCloseBtn=False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self.browserCtrl.load( parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn)
class PersonalMissionDetailsContainerView( LobbySubView, PersonalMissionDetailsContainerViewMeta): eventsCache = dependency.descriptor(IEventsCache) __metaclass__ = event_bus_handlers.EventBusListener def __init__(self, ctx=None): super(PersonalMissionDetailsContainerView, self).__init__(ctx) self.__selectedQuestID = 0 self._initialize(ctx) self.__quests = self.__getQuests() quest = self.__quests.get(self.__selectedQuestID) mayPawn = self.eventsCache.random.getFreeTokensCount( ) >= quest.getPawnCost() and quest.canBePawned() self.__storage = getTutorialGlobalStorage() if self.__storage: self.__storage.setValue(MAY_PAWN_PERSONAL_MISSION, mayPawn) def closeView(self): self.destroy() def useSheet(self, eventID): self._pawnMission(eventID) def startMission(self, eventID): self._processMission(eventID) def obtainAward(self, eventID): LOG_ERROR( 'Award obtain from personal mission details view is not available.' ) def onChangePage(self, eventID): self.__selectedQuestID = int(eventID) quest = self.__quests.get(self.__selectedQuestID) mayPawn = self.eventsCache.random.getFreeTokensCount( ) >= quest.getPawnCost() and quest.canBePawned() if self.__storage: self.__storage.setValue(MAY_PAWN_PERSONAL_MISSION, mayPawn) vehicleSelector = self.components.get( QUESTS_ALIASES.PERSONAL_MISSIONS_VEHICLE_SELECTOR_ALIAS) criteria, extraConditions = getDetailedMissionData( quest).getVehicleRequirementsCriteria() vehicleSelector.as_closeS() vehicleSelector.setSelectedQuest(self.__selectedQuestID) if criteria and quest.isInProgress() and quest.isAvailable()[0]: vehicleSelector.setCriteria(criteria, extraConditions) else: vehicleSelector.as_hideSelectedVehicleS() def declineMission(self, eventID): self._declineMission(eventID) def retryMission(self, eventID): self._processMission(eventID) def _initialize(self, ctx=None): ctx = ctx or {} self.__selectedQuestID = int(ctx.get('eventID', 0)) @decorators.process('updating') def _processMission(self, eventID): quest = events_helpers.getPersonalMissionsCache().getQuests()[int( eventID)] result = yield events_helpers.getPersonalMissionsSelectProcessor()( quest, events_helpers.getPersonalMissionsCache()).request() if result and result.userMsg: SystemMessages.pushMessage(result.userMsg, type=result.sysMsgType) @decorators.process('updating') def _declineMission(self, eventID): result = yield events_helpers.getPersonalMissionsRefuseProcessor()( events_helpers.getPersonalMissionsCache().getQuests()[int( eventID)], events_helpers.getPersonalMissionsCache()).request() if result.userMsg: SystemMessages.pushMessage(result.userMsg, type=result.sysMsgType) @decorators.process('updating') def _pawnMission(self, eventID): quest = events_helpers.getPersonalMissionsCache().getQuests()[int( eventID)] result = yield events_helpers.getPersonalMissionsPawnProcessor()( quest).request() if result and result.userMsg: SystemMessages.pushMessage(result.userMsg, type=result.sysMsgType) def _populate(self): super(PersonalMissionDetailsContainerView, self)._populate() self.eventsCache.onSyncCompleted += self.__setData self.eventsCache.onProgressUpdated += self._onProgressUpdated self.__setData() def _invalidate(self, ctx=None): self._initialize(ctx) self.__setData() def _dispose(self): super(PersonalMissionDetailsContainerView, self)._dispose() self.eventsCache.onSyncCompleted -= self.__setData self.eventsCache.onProgressUpdated -= self._onProgressUpdated self.__storage = None self.__quests = None return def _onProgressUpdated(self, _): self.__quests = self.__getQuests() self.__setData() @event_bus_handlers.eventBusHandler( events.HideWindowEvent.HIDE_PERSONAL_MISSION_DETAILS_VIEW, EVENT_BUS_SCOPE.LOBBY) def __handleDetailsClose(self, _): self.closeView() def __getQuests(self): selectedQuest = self.eventsCache.personalMissions.getQuests().get( self.__selectedQuestID, None) tile = self.eventsCache.personalMissions.getOperations()[ selectedQuest.getOperationID()] quests = tile.getQuestsByFilter(lambda q: bool( selectedQuest.getVehicleClasses() & q.getVehicleClasses())) return quests def __setData(self): datailedList = [] for _, q in enumerate( sorted(self.__quests.itervalues(), key=methodcaller('getID'))): datailedList.append(getDetailedMissionData(q).getInfo()) pages = map( lambda (i, mission): { 'buttonsGroup': 'MissionDetailsPageGroup', 'pageIndex': i, 'label': '%i' % (i + 1), 'tooltip': { 'isSpecial': True, 'specialAlias': TOOLTIPS_CONSTANTS. PERSONAL_MISSIONS_MAP_REGION, 'specialArgs': [int(mission.get('eventID')), 0] }, 'status': mission.get('status'), 'selected': self.__selectedQuestID == int( mission.get('eventID')) }, enumerate(datailedList)) self.as_setInitDataS({ 'title': 'Title', 'missions': datailedList, 'pages': pages })
class ChannelsCarouselHandler(object): __platoonCtrl = dependency.descriptor(IPlatoonController) def __init__(self, guiEntry): super(ChannelsCarouselHandler, self).__init__() self.__guiEntry = guiEntry self.__channelsDP = None self.__preBattleChannelsDP = None self.__handlers = {} self.__showByReqs = {} self.__notifiedMessages = {} return @sf_lobby def app(self): return None def init(self): self.__channelsDP = ChannelsDataProvider() self.__preBattleChannelsDP = ChannelsDataProvider() add = g_eventBus.addListener add(ChannelManagementEvent.REQUEST_TO_ADD, self.__handleRequestToAdd, scope=EVENT_BUS_SCOPE.LOBBY) add(PreBattleChannelEvent.REQUEST_TO_ADD_PRE_BATTLE_CHANNEL, self.__handleRequestToAddPrebattle, scope=EVENT_BUS_SCOPE.LOBBY) add(PreBattleChannelEvent.REQUEST_TO_REMOVE_PRE_BATTLE_CHANNEL, self.__handleRequestToRemovePreBattle, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelManagementEvent.REQUEST_TO_REMOVE, self.__handleRequestToRemove, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelManagementEvent.REQUEST_TO_CHANGE, self.__handleRequestToChange, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelManagementEvent.REQUEST_TO_SHOW, self.__handleRequestToShow, scope=EVENT_BUS_SCOPE.LOBBY) def clear(self): self.__guiEntry = None self.__handlers.clear() self.__notifiedMessages.clear() if self.__channelsDP is not None: self.__channelsDP.clear() self.__channelsDP.finiGUI() self.__channelsDP = None if self.__preBattleChannelsDP is not None: self.__preBattleChannelsDP.clear() self.__preBattleChannelsDP.finiGUI() self.__preBattleChannelsDP = None remove = g_eventBus.removeListener remove(ChannelManagementEvent.REQUEST_TO_ADD, self.__handleRequestToAdd, scope=EVENT_BUS_SCOPE.LOBBY) remove(PreBattleChannelEvent.REQUEST_TO_ADD_PRE_BATTLE_CHANNEL, self.__handleRequestToAddPrebattle, scope=EVENT_BUS_SCOPE.LOBBY) remove(PreBattleChannelEvent.REQUEST_TO_REMOVE_PRE_BATTLE_CHANNEL, self.__handleRequestToRemovePreBattle, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelManagementEvent.REQUEST_TO_REMOVE, self.__handleRequestToRemove, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelManagementEvent.REQUEST_TO_CHANGE, self.__handleRequestToChange, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelManagementEvent.REQUEST_TO_SHOW, self.__handleRequestToShow, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.CAROUSEL_DESTROYED, self.__handleCarouselDestroyed, scope=EVENT_BUS_SCOPE.LOBBY) return def start(self): add = g_eventBus.addListener add(ChannelCarouselEvent.CAROUSEL_INITED, self.__handleCarouselInited, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.OPEN_BUTTON_CLICK, self.__handleOpenButtonClick, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.MINIMIZE_ALL_CHANNELS, self.__handlerMinimizeAll, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.CLOSE_ALL_EXCEPT_CURRENT, self.__handlerCloseAllExceptCurrent, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.CLOSE_BUTTON_CLICK, self.__handleCloseButtonClick, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.ON_WINDOW_CHANGE_FOCUS, self.__handleOnWindowChangeFocus, scope=EVENT_BUS_SCOPE.LOBBY) add(ChannelCarouselEvent.ON_WINDOW_CHANGE_OPEN_STATE, self.__handleOnWindowChangeOpenState, scope=EVENT_BUS_SCOPE.LOBBY) def stop(self): remove = g_eventBus.removeListener remove(ChannelCarouselEvent.CAROUSEL_INITED, self.__handleCarouselInited, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.OPEN_BUTTON_CLICK, self.__handleOpenButtonClick, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.MINIMIZE_ALL_CHANNELS, self.__handlerMinimizeAll, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.CLOSE_ALL_EXCEPT_CURRENT, self.__handlerCloseAllExceptCurrent, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.CLOSE_BUTTON_CLICK, self.__handleCloseButtonClick, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.ON_WINDOW_CHANGE_FOCUS, self.__handleOnWindowChangeFocus, scope=EVENT_BUS_SCOPE.LOBBY) remove(ChannelCarouselEvent.ON_WINDOW_CHANGE_OPEN_STATE, self.__handleOnWindowChangeOpenState, scope=EVENT_BUS_SCOPE.LOBBY) self.__showByReqs.clear() def addChannel(self, channel, lazy=False, isNotified=False): clientID = channel.getClientID() isSystem = channel.isSystem() if lazy: order = channel_num_gen.getOrder4LazyChannel(channel.getName()) openHandler = lambda: events_dispatcher.showLazyChannelWindow( clientID) else: order = channel_num_gen.genOrder4Channel(channel) openHandler = lambda: events_dispatcher.showLobbyChannelWindow( clientID) self.__handlers[clientID] = (ChannelFindCriteria(clientID), openHandler, WindowLayer.WINDOW) self.__channelsDP.addItem( clientID, { 'label': channel.getFullName(), 'canClose': not isSystem, 'isNotified': isNotified, 'icon': None, 'order': order, 'isInProgress': False }) return def removeChannel(self, channel): clientID = channel.getClientID() if clientID in self.__handlers: criteria, _, layer = self.__handlers.pop(clientID) window = None app = self.app if app is not None and app.containerManager is not None: window = app.containerManager.getView(layer, criteria) if window is not None: window.destroy() self.__channelsDP.removeItem(clientID) return def notifyChannel(self, channel, message): clientID = channel.getClientID() self.__setItemField(clientID, 'isNotified', True) if clientID not in self.__notifiedMessages: self.__notifiedMessages[clientID] = [] notifiedMessages = self.__notifiedMessages[clientID] notifiedMessages.append(message) def __setItemField(self, clientID, key, value): result = self.__preBattleChannelsDP.setItemField(clientID, key, value) if not result: result = self.__channelsDP.setItemField(clientID, key, value) return result def updateChannel(self, channel): self.__setItemField(channel.getClientID(), 'label', channel.getFullName()) def removeChannels(self): if self.__channelsDP is not None: self.__channelsDP.clear() if self.__preBattleChannelsDP is not None: self.__preBattleChannelsDP.clear() self.__handlers.clear() self.__showByReqs.clear() self.__notifiedMessages.clear() return def __handleCarouselInited(self, event): carousel = event.target if isinstance(carousel, ChannelCarouselMeta): self.__channelsDP.initGUI(carousel.as_getDataProviderS()) self.__preBattleChannelsDP.initGUI( carousel.as_getBattlesDataProviderS()) g_eventBus.addListener(ChannelCarouselEvent.CAROUSEL_DESTROYED, self.__handleCarouselDestroyed, scope=EVENT_BUS_SCOPE.LOBBY) else: LOG_ERROR('Channel carousel must be extends ChannelCarouselMeta', carousel) def __handleCarouselDestroyed(self, _): self.__channelsDP.finiGUI() self.__preBattleChannelsDP.finiGUI() g_eventBus.removeListener(ChannelCarouselEvent.CAROUSEL_DESTROYED, self.__handleCarouselDestroyed, scope=EVENT_BUS_SCOPE.LOBBY) def __handleRequestToAddPrebattle(self, event): self.__adjustAndAddChannel(event, self.__preBattleChannelsDP) def __handleRequestToAdd(self, event): self.__adjustAndAddChannel(event, self.__channelsDP) def __adjustAndAddChannel(self, event, targetList): ctx = event.ctx label = ctx.get('label') if label is None: LOG_ERROR('Label is not defined', event.ctx) return else: criteria = ctx.get('criteria') if criteria is None: LOG_ERROR('Criteria is not defined', event.ctx) return openHandler = ctx.get('openHandler') if openHandler is None: LOG_ERROR('Open handler is not defined', event.ctx) return layer = ctx.get('layer') if layer is None: LOG_ERROR('View type is not defined', event.ctx) return clientID = event.clientID if clientID not in self.__handlers: self.__handlers[clientID] = (criteria, openHandler, layer) targetList.addItem(clientID, ctx) return def __handleRequestToRemovePreBattle(self, event): self.__removeChannelFromList(event, self.__preBattleChannelsDP) def __handleRequestToRemove(self, event): self.__removeChannelFromList(event, self.__channelsDP) def __removeChannelFromList(self, event, targetList): clientID = event.clientID if clientID in self.__handlers: criteria, _, layer = self.__handlers.pop(clientID) if event.ctx.get('closeWindow', True) and self.app is not None: window = self.app.containerManager.getView(layer, criteria) if window is not None: window.destroy() targetList.removeItem(clientID) self.__showByReqs.pop(clientID, None) return def __handleRequestToChange(self, event): ctx = event.ctx key = ctx.get('key') if key is None: LOG_ERROR('Key of item field is not defined', ctx) return else: value = ctx.get('value') if value is None: LOG_ERROR('Value of item field is not defined', ctx) return clientID = event.clientID if 'isShowByReq' in ctx and ctx['isShowByReq'] is True: self.__showByReqs[clientID] = (key, value) isShow = ctx.get('showIfClosed', False) if isShow: if clientID not in self.__handlers: return criteria, _, layer = self.__handlers[clientID] window = self.app.containerManager.getView(layer, criteria) if window is None: if not self.__setItemField(clientID, key, value): self.__showByReqs.pop(clientID) else: self.__setItemField(clientID, key, value) self.__showByReqs.pop(clientID, None) return def __handleRequestToShow(self, event): ctx = event.ctx show = ctx.get('show') if show is None: LOG_ERROR('Flag "show" is not defined', ctx) return else: clientID = event.clientID if not clientID: return if clientID in self.__showByReqs: key, value = self.__showByReqs[clientID] if show: if not self.__setItemField(clientID, key, value): self.__showByReqs.pop(clientID) elif not self.__channelsDP.clearItemField(clientID, key): if not self.__preBattleChannelsDP.clearItemField( clientID, key): self.__showByReqs.pop(clientID) return def __handleOpenButtonClick(self, event): clientID = event.clientID if not clientID: return elif clientID not in self.__handlers: return else: criteria, openHandler, layer = self.__handlers[clientID] viewContainer = self.app.containerManager if layer == WindowLayer.WINDOW: window = viewContainer.getView(layer, criteria) if window is not None: wName = window.uniqueName isOnTop = viewContainer.as_isOnTopS( WindowLayer.WINDOW, wName) if not isOnTop: viewContainer.as_bringToFrontS(WindowLayer.WINDOW, wName) else: window.onWindowMinimize() return elif layer == WindowLayer.SUB_VIEW: view = viewContainer.getView(layer, criteria) if hasattr(view, 'onWindowMinimize') and callable( getattr(view, 'onWindowMinimize')): view.onWindowMinimize() return fields = {'isNotified': False, 'isInProgress': False} if not self.__channelsDP.setItemFields(clientID, fields): self.__preBattleChannelsDP.setItemFields(clientID, fields) if clientID in self.__notifiedMessages: notifiedMessages = self.__notifiedMessages[clientID] channel = self.__guiEntry.channelsCtrl.getController( clientID).getChannel() for message in notifiedMessages: channel.setMessageShown(message) openHandler() return def __handlerMinimizeAll(self, _): for criteria, _, layer in self.__handlers.itervalues(): viewContainer = self.app.containerManager if isinstance(criteria, ChannelFindCriteria): window = viewContainer.getView(layer, criteria) if window is not None: window.onWindowMinimize() return def __handlerCloseAllExceptCurrent(self, event): self.__closeExcept(event.clientID) def __closeExcept(self, clientID): clientIDs = self.__handlers.keys() for key in clientIDs: if key != clientID: cntrler = self.__guiEntry.channelsCtrl.getController(key) if cntrler is not None: channel = cntrler.getChannel() if not channel.isSystem(): self.__closeChannel(key) return def __handleCloseButtonClick(self, event): clientID = event.clientID channel = self.__guiEntry.channelsCtrl.getController( clientID).getChannel() if not channel.isSystem(): self.__closeChannel(clientID) def __handleOnWindowChangeFocus(self, event): self.__updateItemField(event.clientID, event.wndType, 'isWindowFocused', event.flag) def __handleOnWindowChangeOpenState(self, event): self.__updateItemField(event.clientID, event.wndType, 'isWindowOpened', event.flag) def __updateItemField(self, clientID, wndType, key, flag): if wndType is not None: if wndType == MESSENGER_CHANNEL_CAROUSEL_ITEM_TYPES.CHANNEL_CAROUSEL_ITEM_TYPE_MESSENGER: self.__channelsDP.setItemField(clientID, key, flag) elif wndType == MESSENGER_CHANNEL_CAROUSEL_ITEM_TYPES.CHANNEL_CAROUSEL_ITEM_TYPE_PREBATTLE: self.__preBattleChannelsDP.setItemField(clientID, key, flag) return def __closeChannel(self, clientID): if not clientID: return elif clientID not in self.__handlers: return else: self.__showByReqs.pop(clientID, None) viewContainer = self.app.containerManager criteria, _, layer = self.__handlers[clientID] if layer == WindowLayer.WINDOW: window = viewContainer.getView(layer, criteria) if window is not None: window.onWindowClose() return if self.__guiEntry: controller = self.__guiEntry.channelsCtrl.getController( clientID) if controller: controller.exit() return
class VehicleAnchorsUpdater(object): __hangarSpace = dependency.descriptor(IHangarSpace) __service = dependency.descriptor(ICustomizationService) __settingsCore = dependency.descriptor(ISettingsCore) def __init__(self, ctx): self.__ctx = ctx self.__vehicleCustomizationAnchors = None self.__processedAnchors = {} self.__menuSlotId = None self.__changedStates = {} self.__closeGroups = DisjointSet() return def startUpdater(self): if self.__vehicleCustomizationAnchors is None: interfaceScale = self.__settingsCore.interfaceScale.get() self.__vehicleCustomizationAnchors = GUI.WGVehicleCustomizationAnchors( interfaceScale) self.__ctx.events.onPropertySheetHidden += self.__onPropertySheetHidden self.__ctx.events.onPropertySheetShown += self.__onPropertySheetShown self.__ctx.events.onItemSelected += self.__onCarouselItemSelected self.__ctx.events.onItemUnselected += self.__onCarouselItemUnselected self.__ctx.events.onItemInstalled += self.__onItemInstalled self.__ctx.events.onItemsRemoved += self.__onItemsRemoved self.__ctx.events.onChangesCanceled += self.__onChangesCanceled self.__ctx.events.onSeasonChanged += self.__onSeasonChanged self.__ctx.events.onAnchorHovered += self.__onAnchorHovered self.__ctx.events.onAnchorUnhovered += self.__onAnchorUnhovered self.__settingsCore.interfaceScale.onScaleExactlyChanged += self.__onInterfaceScaleChanged entity = self.__hangarSpace.getVehicleEntity() if entity is not None and entity.appearance is not None: entity.appearance.loadState.subscribe( self.__onVehicleLoadFinished, self.__onVehicleLoadStarted) return def stopUpdater(self): if self.__vehicleCustomizationAnchors is not None: self.__ctx.events.onPropertySheetHidden -= self.__onPropertySheetHidden self.__ctx.events.onPropertySheetShown -= self.__onPropertySheetShown self.__ctx.events.onItemSelected -= self.__onCarouselItemSelected self.__ctx.events.onItemUnselected -= self.__onCarouselItemUnselected self.__ctx.events.onItemInstalled -= self.__onItemInstalled self.__ctx.events.onItemsRemoved -= self.__onItemsRemoved self.__ctx.events.onChangesCanceled -= self.__onChangesCanceled self.__ctx.events.onSeasonChanged -= self.__onSeasonChanged self.__ctx.events.onAnchorHovered -= self.__onAnchorHovered self.__ctx.events.onAnchorUnhovered -= self.__onAnchorUnhovered self.__settingsCore.interfaceScale.onScaleExactlyChanged -= self.__onInterfaceScaleChanged entity = self.__hangarSpace.getVehicleEntity() if entity is not None and entity.appearance is not None: entity.appearance.loadState.unsubscribe( self.__onVehicleLoadFinished, self.__onVehicleLoadStarted) self.__delAllAnchors() self.__vehicleCustomizationAnchors = None return def setAnchors(self, displayObjects): if self.__vehicleCustomizationAnchors is None: _logger.error('Missing WGVehicleCustomizationAnchors.') return else: self.__delAllAnchors() modeId = self.__ctx.modeId tabId = self.__ctx.mode.tabId styleSlot = C11nId(areaId=Area.MISC, slotType=GUI_ITEM_TYPE.STYLE, regionIdx=0) styleAnchorParams = self.__ctx.mode.getAnchorParams(styleSlot) for displayObject in displayObjects: if not hasattr(displayObject, 'slotData'): _logger.error( 'Incorrect anchor displayObject. Missing slotData section. %s', displayObject) continue slotData = displayObject.slotData slotId = C11nId(areaId=slotData.slotId.areaId, slotType=slotData.slotId.slotType, regionIdx=slotData.slotId.regionIdx) anchorParams = self.__ctx.mode.getAnchorParams(slotId) if anchorParams is None: _logger.error('Failed to get anchor params for slotId: %s', slotId) continue if modeId == CustomizationModes.EDITABLE_STYLE and slotId.slotType in EDITABLE_STYLE_APPLY_TO_ALL_AREAS_TYPES: location = styleAnchorParams.location else: location = anchorParams.location linesPosition = copy(location.position) slotWidth = 0.0 if tabId in (CustomizationTabs.EMBLEMS, CustomizationTabs.INSCRIPTIONS): slotWidth = anchorParams.descriptor.size slotHeight = slotWidth * SLOT_ASPECT_RATIO[slotId.slotType] linesShift = slotHeight * _LINES_SHIFT linesPosition -= location.up * linesShift position = location.position direction = location.normal uid = self.__vehicleCustomizationAnchors.addAnchor( position, direction, linesPosition, slotWidth, displayObject, True, True, False, True) anchor = Anchor(slotId, uid, position, direction) if slotId.slotType == GUI_ITEM_TYPE.PROJECTION_DECAL: self.__closeGroups.add(slotId) for aId, a in self.__processedAnchors.iteritems(): dist = (a.position - anchor.position).length if dist < _MIN_PROJECTION_DECAL_ANCHORS_DIST: self.__closeGroups.union(aId, slotId) self.__processedAnchors[slotId] = anchor anchor.setup() self.__changeAnchorsStates() self.__updateAnchorsVisability() return def setCollisions(self): entity = self.__hangarSpace.getVehicleEntity() if entity and entity.appearance and entity.appearance.isLoaded(): collisions = entity.appearance.collisions if collisions is not None: self.__vehicleCustomizationAnchors.setCollisions(collisions) else: _logger.error( 'Collision component for current vehicle is missing.') else: _logger.error('Vehicle entity is not loaded/exist.') return def updateAnchorPositionAndNormal(self, slotId, position, normal): if slotId in self.__processedAnchors: anchor = self.__processedAnchors[slotId] self.__vehicleCustomizationAnchors.updateAnchorPositionAndNormal( anchor.uid, position, normal) def setAnchorShift(self, slotId, shift): if slotId in self.__processedAnchors: anchor = self.__processedAnchors[slotId] self.__vehicleCustomizationAnchors.setAnchorShift( anchor.uid, shift) def changeAnchorParams(self, slotId, isDisplayed, isAutoScalable, isCollidable=False, isActive=True): if slotId in self.__processedAnchors: anchor = self.__processedAnchors[slotId] self.__vehicleCustomizationAnchors.changeAnchorParams( anchor.uid, isDisplayed, isAutoScalable, isCollidable, isActive) def setMenuParams(self, menuDisplayObject, menuWidth, menuHeight, menuCenterX, menuCenterY): self.__vehicleCustomizationAnchors.setMenuParams( menuDisplayObject, menuWidth, menuHeight, menuCenterX, menuCenterY) def displayMenu(self, display): self.__vehicleCustomizationAnchors.displayMenu(display) def displayLine(self, display): self.__vehicleCustomizationAnchors.displayLine(display) def attachMenuToAnchor(self, slotId): if slotId in self.__processedAnchors: anchor = self.__processedAnchors[slotId] self.__vehicleCustomizationAnchors.attachMenuToAnchor(anchor.uid) def setMainView(self, displayObject): return self.__vehicleCustomizationAnchors.setMainView(displayObject) def hideAllAnchors(self): if self.__vehicleCustomizationAnchors is not None: for slotId in self.__processedAnchors: self.changeAnchorParams(slotId, isDisplayed=False, isAutoScalable=False) return def registerInscriptionController(self, inscriptionController, inputLines): self.__vehicleCustomizationAnchors.registerInscriptionController( inscriptionController, inputLines) def __delAllAnchors(self): if self.__vehicleCustomizationAnchors is not None: for anchor in self.__processedAnchors.itervalues(): self.__vehicleCustomizationAnchors.delAnchor(anchor.uid) anchor.destroy() self.__processedAnchors.clear() self.__closeGroups.clear() return def __updateAnchorsVisability(self): if self.__ctx.mode.isRegion: self.__updateRegionsAnchorsVisability() elif self.__ctx.mode.tabId in (CustomizationTabs.EMBLEMS, CustomizationTabs.INSCRIPTIONS): self.__updateDecalAnchorsVisability() elif self.__ctx.mode.tabId == CustomizationTabs.PROJECTION_DECALS: self.__updateProjectionDecalAnchorsVisability() def __updateRegionsAnchorsVisability(self): outfit = self.__ctx.mode.currentOutfit for slotId in self.__processedAnchors: isDisplayed = isSlotFilled(outfit, slotId) isAutoScalable = self.__menuSlotId != slotId self.changeAnchorParams(slotId, isDisplayed=isDisplayed, isAutoScalable=isAutoScalable) def __updateDecalAnchorsVisability(self): for slotId in self.__processedAnchors: isDisplayed = slotId != self.__menuSlotId self.changeAnchorParams(slotId, isDisplayed=isDisplayed, isAutoScalable=True) def __updateProjectionDecalAnchorsVisability(self): formfactor = None item = self.__ctx.mode.selectedItem if item is not None: formfactor = item.formfactor visibleAnchors = defaultdict(set) outfit = self.__ctx.mode.currentOutfit for slotId in self.__processedAnchors: if isSlotFilled(outfit, slotId): isDisplayed = self.__menuSlotId != slotId self.changeAnchorParams(slotId, isDisplayed=isDisplayed, isAutoScalable=True) root = self.__closeGroups.find(slotId) if root is not None: visibleAnchors[root].add(slotId) continue if formfactor is not None: anchor = g_currentVehicle.item.getAnchorBySlotId( slotId.slotType, slotId.areaId, slotId.regionIdx) if anchor.isFitForFormfactor(formfactor): self.changeAnchorParams(slotId, isDisplayed=True, isAutoScalable=True, isCollidable=True) root = self.__closeGroups.find(slotId) if root is not None: visibleAnchors[root].add(slotId) continue self.changeAnchorParams(slotId, isDisplayed=False, isAutoScalable=False) self.__spreadAnchorsApart(visibleAnchors) return def __spreadAnchorsApart(self, visibleAnchors): for slotIds in visibleAnchors.itervalues(): anchorsCount = len(slotIds) if anchorsCount > 1: radius = _MIN_PROJECTION_DECAL_ANCHORS_DIST * 0.5 / math.sin( math.pi / anchorsCount) position = sum( (self.__processedAnchors[slotId].position for slotId in slotIds), Vector3()) / anchorsCount direction = sum( (self.__processedAnchors[slotId].direction for slotId in slotIds), Vector3()) / anchorsCount transformMatrix = Math.Matrix() transformMatrix.lookAt(position, direction, (0, 1, 0)) transformMatrix.invert() shift = Vector3(0, radius, 0) angle = 2 * math.pi / anchorsCount rotor = Math.Matrix() rotor.setRotateZ(angle) for slotId in sorted(slotIds, key=getProjectionSlotFormfactor): anchor = self.__processedAnchors[slotId] newPosition = transformMatrix.applyPoint(shift) anchor.setShift(newPosition - anchor.position) self.setAnchorShift(slotId, anchor.shift) shift = rotor.applyPoint(shift) slotId = slotIds.pop() self.setAnchorShift(slotId, Vector3()) def __onPropertySheetHidden(self): self.__menuSlotId = None self.__updateAnchorsVisability() return def __onPropertySheetShown(self, slotId): self.__menuSlotId = slotId self.__updateAnchorsVisability() def __onCarouselItemSelected(self, *_, **__): if self.__ctx.mode.tabId == CustomizationTabs.PROJECTION_DECALS: self.__updateAnchorsVisability() def __onCarouselItemUnselected(self, *_, **__): if self.__ctx.mode.tabId == CustomizationTabs.PROJECTION_DECALS: for anchor in self.__processedAnchors.itervalues(): anchor.state.onItemUnselected() self.__changeAnchorsStates() self.__updateAnchorsVisability() def __onItemInstalled(self, item, slotId, season, component): anchor = self.__processedAnchors.get(slotId) if anchor is not None: anchor.state.onItemInstalled() outfit = self.__ctx.mode.currentOutfit if isItemsQuantityLimitReached(outfit, slotId.slotType): for anchor in self.__processedAnchors.itervalues(): anchor.state.onLocked() self.__changeAnchorsStates() self.__updateAnchorsVisability() return def __onItemsRemoved(self, *_, **__): self.__updateAnchorsState() self.__updateAnchorsVisability() def __onChangesCanceled(self, *_, **__): self.__updateAnchorsState() self.__updateAnchorsVisability() def __onSeasonChanged(self, *_, **__): self.__updateAnchorsState() self.__updateAnchorsVisability() def __onAnchorHovered(self, slotId): if self.__ctx.mode.tabId != CustomizationTabs.PROJECTION_DECALS: return elif self.__ctx.mode.selectedItem is None: return else: anchor = self.__processedAnchors.get(slotId) if anchor is not None: item = self.__ctx.mode.getItemFromSlot(slotId) if item is not None and item.intCD == self.__ctx.mode.selectedItem.intCD: return anchor.state.onHovered() self.__changeAnchorsStates() return def __onAnchorUnhovered(self, slotId): if self.__ctx.mode.tabId != CustomizationTabs.PROJECTION_DECALS: return elif self.__ctx.mode.selectedItem is None: return else: anchor = self.__processedAnchors.get(slotId) if anchor is not None: anchor.state.onUnhovered() self.__changeAnchorsStates() return def __updateAnchorsState(self): for anchor in self.__processedAnchors.itervalues(): anchor.updateState() self.__changeAnchorsStates() def onAnchorStateChanged(self, uid, state): if state is not None: self.__changedStates[uid] = state return def onCameraLocated(self, locatedSlotId=None): for slotId, anchor in self.__processedAnchors.iteritems(): if slotId == locatedSlotId: anchor.state.onSelected() anchor.state.onUnselected() self.__changeAnchorsStates() def getAnchorState(self, slotId): if slotId in self.__processedAnchors: anchor = self.__processedAnchors[slotId] return anchor.stateID def __changeAnchorsStates(self): if self.__changedStates: self.__ctx.events.onAnchorsStateChanged(self.__changedStates) self.__changedStates.clear() def __onVehicleChanged(self): self.setCollisions() def __onVehicleLoadStarted(self): pass def __onVehicleLoadFinished(self): self.setCollisions() def __onInterfaceScaleChanged(self, scale): self.__vehicleCustomizationAnchors.setInterfaceScale(scale) def getProcessedAnchor(self, slotId): return self.__processedAnchors[ slotId] if slotId in self.__processedAnchors else None
class _VehicleCompareCartDataProvider(SortableDAAPIDataProvider): itemsCache = dependency.descriptor(IItemsCache) comparisonBasket = dependency.descriptor(IVehicleComparisonBasket) def __init__(self): super(_VehicleCompareCartDataProvider, self).__init__() self._list = [] self._listMapping = {} self.__mapping = {} self.__selectedID = None return @property def collection(self): return self._list def emptyItem(self): return None def clear(self): self._list = [] self._listMapping.clear() self.__mapping.clear() self.__selectedID = None return def fini(self): self.comparisonBasket.onChange -= self.__basketChanged self.comparisonBasket.onSwitchChange -= self.__basketChanged self.clear() self.destroy() def getSelectedIdx(self): return self.__mapping[self.__selectedID] if self.__selectedID in self.__mapping else -1 def setSelectedID(self, selId): self.__selectedID = selId def setFlashObject(self, movieClip, autoPopulate=True, setScript=True): self.comparisonBasket.onChange += self.__basketChanged self.comparisonBasket.onSwitchChange += self.__basketChanged return super(_VehicleCompareCartDataProvider, self).setFlashObject(movieClip, autoPopulate, setScript) def getVO(self, index): vo = None if index > -1: try: vo = self.sortedCollection[index] except IndexError: LOG_ERROR('Item not found', index) return vo def buildList(self, changedVehsCDs): self.clear() for idx, vehCD in enumerate(changedVehsCDs): self._list.append(self._makeVO(vehCD, idx)) def rebuildList(self, cache): self.buildList(cache) self.refresh() def pyGetSelectedIdx(self): return self.getSelectedIdx() def refreshRandomItems(self, indexes, items): self.flashObject.invalidateItems(indexes, items) def refreshSingleItem(self, index, item): self.flashObject.invalidateItem(index, item) def _makeVO(self, vehicleCD, index): vehicle = self.itemsCache.items.getItemByCD(vehicleCD) complectation = _ms(VEH_COMPARE.cartpopover_configurationtype(self.comparisonBasket.getVehicleAt(index).getConfigurationType())) basketLocked = self.comparisonBasket.isLocked return {'id': vehicleCD, 'index': index, 'vehicleName': text_styles.main(vehicle.shortUserName), 'complectation': complectation, 'nation': getNationsFilterAssetPath(AVAILABLE_NAMES[vehicle.nationID]), 'level': vehicle.level, 'typeStr': getTypeSmallIconPath(vehicle.type, vehicle.isPremium), 'smallIconPath': vehicle.iconSmall, 'removeBtnTooltip': VEH_COMPARE.CARTPOPOVER_REMOVELOCKEDBTN_TOOLTIP if basketLocked else VEH_COMPARE.CARTPOPOVER_REMOVEBTN_TOOLTIP, 'removeBtnEnabled': not basketLocked} def __basketChanged(self, *args): self.rebuildList(self.comparisonBasket.getVehiclesCDs())
class TankmanCurrentVehicleAttrField(ToolTipAttrField): itemsCache = dependency.descriptor(IItemsCache) def _getItem(self): tankman = self._tooltip.item return self.itemsCache.items.getVehicle(tankman.vehicleInvID) if tankman and tankman.isInTank else None
class TankmanNativeVehicleAttrField(ToolTipAttrField): itemsCache = dependency.descriptor(IItemsCache) def _getItem(self): tankman = self._tooltip.item return self.itemsCache.items.getItemByCD(tankman.vehicleNativeDescr.type.compactDescr)
class Customization(FittingItem): __slots__ = ('_boundVehicles', '_bonus', '_installedVehicles', '__noveltyData', '__progressingData', '__installedCount', '__boundInventoryCount', '__fullInventoryCount', '__fullCount') eventsCache = dependency.descriptor(IEventsCache) def __init__(self, intCompactDescr, proxy=None): super(Customization, self).__init__(intCompactDescr, proxy) self._inventoryCount = 0 self._bonus = None self._boundVehicles = {} self._installedVehicles = {} self.__noveltyData = [] self.__progressingData = {} self.__installedCount = None self.__boundInventoryCount = None self.__fullInventoryCount = None self.__fullCount = None if proxy is not None and proxy.inventory.isSynced(): installedVehicles = proxy.inventory.getC11nItemAppliedVehicles( self.intCD) invCount = proxy.inventory.getItems(GUI_ITEM_TYPE.CUSTOMIZATION, self.intCD) for vehicleCD in installedVehicles: self._installedVehicles[ vehicleCD] = proxy.inventory.getC11nItemAppliedOnVehicleCount( self.intCD, vehicleCD) for vehIntCD, count in invCount.iteritems(): self._boundVehicles[vehIntCD] = count self._inventoryCount = self._boundVehicles.pop(UNBOUND_VEH_KEY, 0) self.__noveltyData = proxy.inventory.getC11nItemNoveltyData( intCompactDescr) self.__progressingData = proxy.inventory.getC11nProgressionDataForItem( intCompactDescr) self._isUnlocked = True return def __cmp__(self, other): return cmp(self.userName, other.userName) if isinstance( other, Customization) else -1 def __repr__(self): return '{}<intCD:{}, id:{}>'.format(self.__class__.__name__, self.intCD, self.id) @property def id(self): return self.descriptor.id @property def itemTypeName(self): return GUI_ITEM_TYPE_NAMES[self.itemTypeID] @property def itemFullTypeName(self): return self.itemTypeName @property def groupID(self): return self.descriptor.parentGroup.itemPrototype.userKey @property def groupUserName(self): return self.descriptor.parentGroup.itemPrototype.userString @property def userTypeID(self): return R.strings.item_types.customization.dyn(self.itemFullTypeName)() @property def userType(self): return backport.text(self.userTypeID) @property def tags(self): return self.descriptor.tags @property def season(self): return self.descriptor.season @property def seasons(self): return [ season for season in SeasonType.SEASONS if season & self.season ] @property def requiredToken(self): return self.descriptor.requiredToken @property def priceGroup(self): return self.descriptor.priceGroup @property def priceGroupTags(self): return self.descriptor.priceGroupTags @property def bonus(self): return self._bonus @property def texture(self): return self.descriptor.texture @property def icon(self): return self.descriptor.texture.replace('gui/', '../', 1) @property def iconUrl(self): return getTextureLinkByID(self.texture) @property def isVehicleBound(self): return ItemTags.VEHICLE_BOUND in self.tags @property def isLimited(self): return self.descriptor.maxNumber > 0 @property def isStyleOnly(self): return self.descriptor.isStyleOnly @property def inventoryCount(self): return self._inventoryCount def getBonusIcon(self, size='small'): return RES_ICONS.getBonusIcon(size, self.itemTypeName) def boundInventoryCount(self, vehicleIntCD=None): if vehicleIntCD is not None: if vehicleIntCD in self._boundVehicles: return self._boundVehicles[vehicleIntCD] return 0 else: if self.__boundInventoryCount is None: self.__boundInventoryCount = sum( self._boundVehicles.itervalues()) return self.__boundInventoryCount def fullInventoryCount(self, vehicleIntCD=None): if vehicleIntCD is not None: return self.inventoryCount + self.boundInventoryCount(vehicleIntCD) else: if self.__fullInventoryCount is None: self.__fullInventoryCount = self.inventoryCount + self.boundInventoryCount( ) return self.__fullInventoryCount def installedCount(self, vehicleIntCD=None): if vehicleIntCD is not None: if vehicleIntCD in self._installedVehicles: return self._installedVehicles[vehicleIntCD] return 0 else: if self.__installedCount is None: self.__installedCount = sum( self._installedVehicles.itervalues()) return self.__installedCount def fullCount(self, vehicleIntCD=None): if vehicleIntCD is not None: return self.fullInventoryCount(vehicleIntCD) + self.installedCount( vehicleIntCD) else: if self.__fullCount is None: self.__fullCount = self.fullInventoryCount( ) + self.installedCount() return self.__fullCount @property def buyCount(self): if self.isHidden: return 0 return max(self.descriptor.maxNumber - self.fullCount(), 0) if self.isLimited else float('inf') @property def mayApply(self): return self.inventoryCount > 0 or self.buyCount > 0 @property def specialEventTag(self): eventTags = (tag for tag in self.tags if tag in SpecialEvents.ALL) return first(eventTags) @property def specialEventIcon(self): return SpecialEvents.ICONS.get(self.specialEventTag, '') @property def specialEventName(self): return SpecialEvents.NAMES.get(self.specialEventTag, '') @property def isProgressive(self): return self.descriptor.progression is not None @property def isProgressionAutoBound(self): return self.descriptor.progression.autobound if self.isProgressive else False @property def progressionConditions(self): return self.descriptor.progression.levels if self.isProgressive else None @property def isProgressionRewindEnabled(self): return ItemTags.PROGRESSION_REWIND_ENABLED in self.tags def getIconApplied(self, component): return self.icon def getInstalledVehicles(self, vehicles=None): return set(self._installedVehicles) def getBoundVehicles(self): return set(self._boundVehicles) def customizationDisplayType(self): return self.descriptor.customizationDisplayType def isDim(self): return ItemTags.DIM in self.tags def isSummer(self): return self.season & SeasonType.SUMMER def isWinter(self): return self.season & SeasonType.WINTER def isDesert(self): return self.season & SeasonType.DESERT def isAllSeason(self): return self.season == SeasonType.ALL def isEvent(self): return self.season & SeasonType.EVENT def mayInstall(self, vehicle, _=None): if not self._matchVehicleTags(vehicle): return False else: itemFilter = self._descriptor.filter return itemFilter is None or itemFilter.matchVehicleType( vehicle.descriptor.type) def isWide(self): return False def isUnlocked(self): return bool( self.eventsCache.questsProgress.getTokenCount( self.requiredToken)) if self.requiredToken else True def isRare(self): return self.descriptor.isRare() def isHiddenInUI(self): return not self._matchVehicleTags( g_currentVehicle.item) or self.descriptor.isHiddenInUI() def getGUIEmblemID(self): pass def isNew(self): return bool(self.__noveltyData) def getNoveltyCounter(self, vehicle): if not self.mayInstall(vehicle): return 0 return sum([ self.__noveltyData.get(key, 0) for key in (UNBOUND_VEH_KEY, vehicle.intCD) ]) @staticmethod def getSpecialArgs(component): return None def getMaxProgressionLevel(self): return len( self.descriptor.progression.levels) if self.isProgressive else -1 def getLatestOpenedProgressionLevel(self, vehicle): vehProgressData = self.getCurrentProgressionDataForVehicle(vehicle) if vehProgressData is not None: return vehProgressData.currentLevel else: return self.descriptor.progression.defaultLvl if self.isProgressive and self.descriptor.progression else -1 def getCurrentProgressOnCurrentLevel(self, vehicle, conditionPath=None): if self.isProgressive: vehProgressData = self.getCurrentProgressionDataForVehicle(vehicle) if vehProgressData is not None: if conditionPath is not None: return vehProgressData.currentProgressOnLevel.get( conditionPath, 0) if vehProgressData.currentProgressOnLevel.values(): return vehProgressData.currentProgressOnLevel.values()[0] return 0 else: return -1 def getMaxProgressOnCurrentLevel(self, vehicle, conditionPath=None): vehProgressData = self.getCurrentProgressionDataForVehicle(vehicle) if vehProgressData is not None: if conditionPath is not None: return vehProgressData.maxProgressOnLevel.get( conditionPath, -1) if vehProgressData.maxProgressOnLevel.values(): return vehProgressData.maxProgressOnLevel.values()[0] return -1 @staticmethod def getTextureByProgressionLevel(baseTexture, progressionLevel): path, name = os.path.split(baseTexture) name, ext = os.path.splitext(name) basePart, delimiter, _ = name.rpartition('_') if not basePart: _logger.error( 'Wrong name of texture for progression customization item (texture name is "%s" )', baseTexture) return '' name = basePart + delimiter + str(progressionLevel) texture = path + '/' + name + ext if not ResMgr.isFile(texture): _logger.error( 'Failed to get texture by progression level. Base texture %s; level: %s', baseTexture, progressionLevel) return '' return texture def getUsedProgressionLevel(self, component, vehicle=None): if self.isProgressive and component: progressionLevel = component.progressionLevel if progressionLevel == 0: progressionLevel = self.getLatestOpenedProgressionLevel( g_currentVehicle.item if vehicle is None else vehicle) return progressionLevel else: return -1 def iconByProgressionLevel(self, progressionLevel): return self.getTextureByProgressionLevel( self.texture, progressionLevel).replace( 'gui/', '../', 1) if self.isProgressive else None def iconUrlByProgressionLevel(self, progressionLevel): return getTextureLinkByID( self.getTextureByProgressionLevel( self.texture, progressionLevel)) if self.isProgressive else None def iconResourceByProgressionLevel(self, progressionLevel): return getImageResourceFromPath( self.getTextureByProgressionLevel( self.texture, progressionLevel)) if self.isProgressive else None def availableForPurchaseProgressive(self, vehicle): if self.isHidden: return 0 elif self.isProgressionAutoBound and vehicle is not None: availableSlotsCount = cc.getAvailableSlotsCount( self.descriptor, vehicle.descriptor) * len( SeasonType.COMMON_SEASONS) installed = self.installedCount(vehicle.intCD) bounded = self.boundInventoryCount(vehicle.intCD) availableToBuy = availableSlotsCount - installed - bounded return max(0, availableToBuy) else: return float('inf') def getProgressionLevel(self, vehicle=None): progress = None if self.isProgressive and self.__progressingData is not None: vehicleCD = UNBOUND_VEH_KEY if vehicle is not None: if not self.mayInstall(vehicle): return -1 vehicleCD = vehicle.intCD if self.isProgressionAutoBound else vehicleCD progress = self.__progressingData.get(vehicleCD) return progress.currentLevel if progress is not None else -1 def getCurrentProgressionDataForVehicle(self, vehicle): if self.isProgressive and self.__progressingData is not None: if vehicle.intCD in self.__progressingData: return self.__progressingData[vehicle.intCD] if UNBOUND_VEH_KEY in self.__progressingData and self.mayInstall( vehicle): return self.__progressingData[UNBOUND_VEH_KEY] return def _matchVehicleTags(self, vehicle): return not (vehicle and vehicle.isProgressionDecalsOnly)
class TankmanTooltipDataBlock(BlocksTooltipData): _itemsCache = dependency.descriptor(IItemsCache) _lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self, context): super(TankmanTooltipDataBlock, self).__init__(context, TOOLTIP_TYPE.SKILL) self._setWidth(320) self.item = None return def _packBlocks(self, *args, **kwargs): items = super(TankmanTooltipDataBlock, self)._packBlocks() item = self.context.buildItem(*args, **kwargs) self.item = item vehicle = None if item.isInTank: vehicle = self._itemsCache.items.getVehicle(item.vehicleInvID) fullUserName = self._getFullUserName(item) items.append(formatters.packImageTextBlockData(title=text_styles.highTitle(fullUserName), desc=text_styles.main(self._getTankmanDescription(item)))) innerBlock = [] if vehicle: self._createLabel(innerBlock) self._createVehicleBlock(innerBlock, vehicle) if innerBlock: items.append(formatters.packBuildUpBlockData(innerBlock, padding=formatters.packPadding(left=0, right=50, top=-5, bottom=0), linkage=BLOCKS_TOOLTIP_TYPES.TOOLTIP_BUILDUP_BLOCK_WHITE_BG_LINKAGE)) commonStatsBlock = [formatters.packTextBlockData(text=makeHtmlString('html_templates:lobby/textStyle', 'grayTitle', {'message': makeString(TOOLTIPS.HANGAR_CREW_SPECIALTY_SKILLS)}))] penalty = self._getBonusValue(item, [TankmanRoleBonusesField.BONUSES.PENALTY]) addition = self._getBonusValue(item, [TankmanRoleBonusesField.BONUSES.COMMANDER, TankmanRoleBonusesField.BONUSES.EQUIPMENTS, TankmanRoleBonusesField.BONUSES.DEVICES, TankmanRoleBonusesField.BONUSES.BROTHERHOOD]) addition_ = '' if addition == 0 else self._getSign(addition) + str(addition) penalty_ = '' if penalty == 0 else self._getSign(penalty) + str(penalty) if penalty != 0 or addition != 0: addRoleLevels = ' (' + str(item.roleLevel) + addition_ + penalty_ + ')' else: addRoleLevels = '' commonStatsBlock.append(formatters.packTextParameterBlockData(self._makeRoleName(item), text_styles.stats(str(item.roleLevel + penalty + addition) + '%' + addRoleLevels), valueWidth=90, padding=formatters.packPadding(left=0, right=0, top=5, bottom=0))) field = self._getSkillList() _, value = field.buildData() skills = value or [] maxPopUpBlocks = 14 for skill in skills[:maxPopUpBlocks]: commonStatsBlock.append(formatters.packTextParameterBlockData(text_styles.main(skill['label']), text_styles.stats(str(skill['level']) + '%'), valueWidth=90)) if len(skills) > maxPopUpBlocks: diff = str(len(skills) - maxPopUpBlocks) commonStatsBlock.append(formatters.packAlignedTextBlockData(text=text_styles.middleTitle(makeString(TOOLTIPS.HANGAR_CREW_MORESKILLS, skill_cnt=diff)), align=BLOCKS_TOOLTIP_TYPES.ALIGN_CENTER)) items.append(formatters.packBuildUpBlockData(commonStatsBlock, gap=5)) self._createBlockForNewSkills(items) self._createMoreInfoBlock(items) return items def _makeRoleName(self, item): vehicle = None nativeVehicle = self._itemsCache.items.getItemByCD(item.vehicleNativeDescr.type.compactDescr) if item.isInTank: vehicle = self._itemsCache.items.getVehicle(item.vehicleInvID) vehicleName = self._getVehicleName(vehicle, nativeVehicle) return text_styles.main(item.roleUserName + ' ') + vehicleName else: return text_styles.main(item.roleUserName) def _getSign(self, val): return '' if val < 0 else '+' def _getBonusValue(self, tankman, ids): result = 0 if tankman: _, roleBonuses = tankman.realRoleLevel for idx in ids: result += roleBonuses[idx] return int(result) def _getFullUserName(self, item): if item.skinID != NO_CREW_SKIN_ID and self._lobbyContext.getServerSettings().isCrewSkinsEnabled(): skinItem = self._itemsCache.items.getCrewSkin(item.skinID) return localizedFullName(skinItem) return item.fullUserName def _getTankmanDescription(self, item): return item.rankUserName def _getVehicleName(self, vehicle=None, nativeVehicle=None): return text_styles.main(nativeVehicle.shortUserName) if not vehicle or nativeVehicle.shortUserName == vehicle.shortUserName else text_styles.critical(nativeVehicle.shortUserName) def _getSkillList(self): return TankmanSkillListField(self, 'skills') def _createLabel(self, innerBlock): innerBlock.append(formatters.packTextBlockData(text=makeHtmlString('html_templates:lobby/textStyle', 'grayTitle', {'message': backport.text(R.strings.tooltips.hangar.crew.assignedTo())}))) def _createVehicleBlock(self, innerBlock, vehicle): vehicleType = vehicle.type.replace('-', '_') innerBlock.append(formatters.packImageTextBlockData(img=vehicle.iconContour, txtGap=-4, padding=formatters.packPadding(bottom=0, top=10, left=0), title=text_styles.stats(vehicle.shortUserName), desc=text_styles.stats(backport.text(R.strings.menu.header.vehicleType.dyn(vehicleType)())), flipHorizontal=True)) def _createBlockForNewSkills(self, items): field = TankmanNewSkillCountField(self, '') _, newSkillCount = field.buildData() return items.append(formatters.packImageTextBlockData(img='../maps/icons/tankmen/skills/small/new_skill.png', txtOffset=20, padding=formatters.packPadding(bottom=0, top=5, left=0), imgPadding=formatters.packPadding(left=0, top=3), title=makeHtmlString('html_templates:lobby/textStyle', 'goldTextTitle', {'message': backport.text(R.strings.tooltips.hangar.crew.new_skill_available.header())}), desc=makeHtmlString('html_templates:lobby/textStyle', 'goldTextField', {'message': backport.text(R.strings.tooltips.hangar.crew.new_skill_available.text())}))) if newSkillCount > 0 else None def _createMoreInfoBlock(self, items): field = TankmanStatusField(self, '') _, value = field.buildData() status = value or {} if 'header' in status and status['header'] != '': items.append(formatters.packImageTextBlockData(title=text_styles.warning(status['header']), desc=makeHtmlString('html_templates:lobby/textStyle', 'statusWarningField', {'message': status['text']})))
class Style(Customization): __slots__ = ('_changableTypes', '_service', '_itemsCache', '__outfits', '__dependenciesByIntCD', '__serialNumber') _service = dependency.descriptor(ICustomizationService) _itemsCache = dependency.descriptor(IItemsCache) def __init__(self, intCompactDescr, proxy=None): super(Style, self).__init__(intCompactDescr, proxy) self.itemTypeID = GUI_ITEM_TYPE.STYLE self._changableTypes = None self.__outfits = {} self.__dependenciesByIntCD = None self.__serialNumber = None if proxy is not None and proxy.isSynced(): self.__serialNumber = proxy.inventory.getC11nSerialNumber( intCompactDescr) return @property def isProgressive(self): return bool(self.descriptor.styleProgressions) @property def isEditable(self): return self.descriptor.isEditable @property def isRentable(self): return self.descriptor.isRent @property def isRented(self): return False if not self.isRentable else bool( self.boundInventoryCount()) @property def isProgressionRequired(self): return ItemTags.PROGRESSION_REQUIRED in self.tags @property def isProgression(self): return ItemTags.STYLE_PROGRESSION in self.tags @property def isWithSerialNumber(self): return ItemTags.STYLE_SERIAL_NUMBER in self.tags @property def is3D(self): return bool(self.modelsSet) @property def rentCount(self): return self.descriptor.rentCount if self.isRentable else 0 @property def modelsSet(self): return self.descriptor.modelsSet @property def userTypeID(self): return getStyleGroupNameResourceID(self.groupID) @property def userType(self): return backport.text(self.userTypeID) @property def alternateItems(self): items = [] for itemType, ids in self.descriptor.alternateItems.iteritems(): for itemId in ids: compactDescr = makeIntCompactDescrByID('customizationItem', itemType, itemId) items.append(self._service.getItemByCD(compactDescr)) return items @property def changeableSlotTypes(self): return self.descriptor.changeableSlotTypes @property def maxProgressionLevel(self): return len(self.descriptor.styleProgressions) @property def serialNumber(self): return self.__serialNumber def getDescription(self): return self.longDescriptionSpecial or self.fullDescription or self.shortDescriptionSpecial or self.shortDescription def getUpgradePrice(self, currentLvl, targetLvl): def _getLevelPrice(level): levelDescr = self.descriptor.progression.levels.get(level) if levelDescr: price = Money(**levelDescr['price']) return ItemPrice(price=price, defPrice=price) return ITEM_PRICE_EMPTY return sum((_getLevelPrice(lvl) for lvl in xrange(currentLvl + 1, targetLvl + 1)), ITEM_PRICE_EMPTY) def getRentInfo(self, vehicle): if not self.isRentable: return RentalInfoProvider() battlesLeft = self.boundInventoryCount(vehicle.intCD) return RentalInfoProvider(battles=battlesLeft) def getOutfit(self, season, vehicleCD='', diff=None): if diff is not None: return self.__createOutfit(season, vehicleCD, diff) else: if season not in self.__outfits or self.__outfits[ season].vehicleCD != vehicleCD: self.__outfits[season] = self.__createOutfit(season, vehicleCD) return self.__outfits[season].copy() def getDependenciesIntCDs(self): if self.__dependenciesByIntCD is None: self.__dependenciesByIntCD = {} makeCD = makeIntCompactDescrByID for ancestorID, dependentData in self.descriptor.dependencies.iteritems( ): dependentIntCDs = [] for iType, iIds in dependentData.iteritems(): dependentIntCDs.extend([ makeCD('customizationItem', iType, iId) for iId in iIds ]) dependentIntCDs = tuple(dependentIntCDs) self.__dependenciesByIntCD[makeCD( 'customizationItem', CustomizationType.CAMOUFLAGE, ancestorID)] = dependentIntCDs return self.__dependenciesByIntCD def isWide(self): return True def isProgressionPurchasable(self, progressionLevel): styleDescr = self._descriptor.compactDescr lockedLevels = self._service.itemsCache.items.shop.getNotInShopProgressionLvlItems( ).get(styleDescr, []) return progressionLevel not in lockedLevels def canBeEditedForVehicle(self, vehicleIntCD): if not self.isEditable: return EditingStyleReason(EDITING_STYLE_REASONS.NOT_EDITABLE) else: ctx = self._service.getCtx() if ctx is not None and self.isProgression: season = ctx.mode.season diff = ctx.stylesDiffsCache.getDiff(self, season) if diff is not None: vehicleItem = self._service.itemsCache.items.getItemByCD( vehicleIntCD) diffOutfit = parseOutfitDescr(outfitDescr=diff) modifiedProgression = diffOutfit.styleProgressionLevel progressionChanged = modifiedProgression != self.getLatestOpenedProgressionLevel( vehicleItem) if progressionChanged and not self.isProgressionPurchasable( modifiedProgression): return EditingStyleReason( EDITING_STYLE_REASONS.NOT_REACHED_LEVEL) if not self.isProgressionRequired: return EditingStyleReason(EDITING_STYLE_REASONS.IS_EDITABLE) progressionStorage = self._itemsCache.items.inventory.getC11nProgressionDataForVehicle( vehicleIntCD) for itemIntCD, progressionData in progressionStorage.iteritems(): if not progressionData.currentLevel: continue item = self._service.getItemByCD(itemIntCD) if self.descriptor.isItemInstallable(item.descriptor): return EditingStyleReason( EDITING_STYLE_REASONS.IS_EDITABLE) return EditingStyleReason( EDITING_STYLE_REASONS.NOT_HAVE_ANY_PROGRESIIVE_DECALS) def isProgressionRequiredCanBeEdited(self, vehicleIntCD): return self.isProgressionRequired and self.canBeEditedForVehicle( vehicleIntCD) def isItemInstallable(self, item): return self.descriptor.isItemInstallable(item.descriptor) def isEditedForVehicle(self, vehicleIntCD): c11nCtx = self._service.getCtx() if c11nCtx is not None and vehicleIntCD == g_currentVehicle.item.intCD: diffs = c11nCtx.stylesDiffsCache.getDiffs(self) for diff in diffs.itervalues(): if diff is not None and isEditedStyle(parseCompDescr(diff)): return True else: outfitsPool = self._itemsCache.items.inventory.getC11nOutfitsFromPool( vehicleIntCD) for styleId, _ in outfitsPool: if styleId == self.id: return True return False def iconByProgressionLevel(self, _): return self.getIconApplied(component=None) def iconUrlByProgressionLevel(self, _): return self.getIconApplied(component=None) def getAdditionalOutfit(self, level, season, vehicleCD): additionalOutfit = self.descriptor.styleProgressions.get( level, {}).get('additionalOutfit', {}) return Outfit( strCompactDescr=additionalOutfit.get(season).makeCompDescr(), vehicleCD=vehicleCD ) if additionalOutfit and additionalOutfit.get(season) else None def __createOutfit(self, season, vehicleCD='', diff=None): component = deepcopy(self.descriptor.outfits[season]) vehDescr = None if vehicleCD: vehDescr = VehicleDescr(vehicleCD) if vehDescr and ItemTags.ADD_NATIONAL_EMBLEM in self.tags: emblems = createNationalEmblemComponents(vehDescr) component.decals.extend(emblems) if vehDescr and self.isProgressive: vehicle = self._itemsCache.items.getItemByCD( vehDescr.type.compactDescr) component.styleProgressionLevel = self.getLatestOpenedProgressionLevel( vehicle) if self.isProgressionRewindEnabled: component.styleProgressionLevel = self.maxProgressionLevel styleOutfitData = self._itemsCache.items.inventory.getOutfitData( vehDescr.type.compactDescr, SeasonType.ALL) if styleOutfitData: styledOutfitComponent = parseCompDescr(styleOutfitData) outfitLvl = styledOutfitComponent.styleProgressionLevel component.styleProgressionLevel = outfitLvl if outfitLvl else 1 if self.isWithSerialNumber and self.serialNumber is not None: component.serial_number = self.serialNumber if diff is not None: diffComponent = parseCompDescr(diff) if component.styleId != diffComponent.styleId: _logger.error( 'Merging outfits of different styles is not allowed. ID1: %s ID2: %s', component.styleId, diffComponent.styleId) else: component = component.applyDiff(diffComponent) return self.itemsFactory.createOutfit(component=component, vehicleCD=vehicleCD)
class BattlePassVotingConfirmView(FullScreenDialogView): __slots__ = ('__data',) __battlePassController = dependency.descriptor(IBattlePassController) __settingsCore = dependency.descriptor(ISettingsCore) __itemsCache = dependency.descriptor(IItemsCache) def __init__(self, data): settings = ViewSettings(R.views.lobby.battle_pass.BattlePassVotingConfirmView()) settings.flags = ViewFlags.OVERLAY_VIEW settings.model = BattlePassVotingConfirmViewModel() self.__data = data super(BattlePassVotingConfirmView, self).__init__(settings) @property def viewModel(self): return self.getViewModel() def _setBaseParams(self, model): reward = self.__data.get('finalReward') vehicle = self.__itemsCache.items.getItemByCD(reward.getVehicleCD()) model.setVehicleName(vehicle.name.split(':')[1]) model.setVehicleCD(reward.getVehicleCD()) model.setStyleName(reward.getStyleName()) model.setRecruitName(reward.getRecruitName()) model.setIsBattlePassBought(self.__battlePassController.isBought()) def _initialize(self): super(BattlePassVotingConfirmView, self)._initialize() self.__battlePassController.onBattlePassSettingsChange += self.__onSettingsChange switchHangarOverlaySoundFilter(on=True) def _finalize(self): super(BattlePassVotingConfirmView, self)._finalize() self.__battlePassController.onBattlePassSettingsChange -= self.__onSettingsChange switchHangarOverlaySoundFilter(on=False) def _addListeners(self): self.viewModel.onVoteClick += self.__onVoteClick def _removeListeners(self): self.viewModel.onVoteClick -= self.__onVoteClick def _blurBackGround(self): pass def __onVoteClick(self, args): vehicleCD = int(args.get('vehicleCD')) self.__chooseFinalReward(vehicleCD, self.__battlePassController.getSeasonID()) def __setVotedWithBoughtBP(self): self.__settingsCore.serverSettings.saveInBPStorage({BattlePassStorageKeys.VOTED_WITH_BOUGHT_BP: self.__battlePassController.isBought()}) @decorators.process('chooseFinalReward') def __chooseFinalReward(self, rewardID, seasonID): result = yield ChooseFinalBattlePassReward(rewardID, seasonID).request() if result.userMsg: SystemMessages.pushMessage(result.userMsg, type=result.sysMsgType) if result.success: self.__setVotedWithBoughtBP() super(BattlePassVotingConfirmView, self)._onAcceptClicked() def __onSettingsChange(self, *_): if not self.__battlePassController.isVisible() or self.__battlePassController.isPaused(): self.destroyWindow()
class SandboxEntity(PreQueueEntity): lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(SandboxEntity, self).__init__(FUNCTIONAL_FLAG.SANDBOX, QUEUE_TYPE.SANDBOX, PreQueueSubscriber()) self.__watcher = None self.storage = prequeue_storage_getter(QUEUE_TYPE.SANDBOX)() return def init(self, ctx=None): self.storage.release() self.__watcher = SandboxVehiclesWatcher() self.__watcher.start() self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingChanged return super(SandboxEntity, self).init(ctx) def fini(self, ctx=None, woEvents=False): if self.__watcher is not None: self.__watcher.stop() self.__watcher = None self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingChanged return super(SandboxEntity, self).fini(ctx=ctx, woEvents=woEvents) def leave(self, ctx, callback=None): if not ctx.hasFlags(FUNCTIONAL_FLAG.TUTORIAL) and not ctx.hasFlags( FUNCTIONAL_FLAG.SANDBOX): self.storage.suspend() super(SandboxEntity, self).leave(ctx, callback) @vehicleAmmoCheck def queue(self, ctx, callback=None): super(SandboxEntity, self).queue(ctx, callback=callback) def doSelectAction(self, action): return SelectResult( True ) if action.actionName == PREBATTLE_ACTION_NAME.SANDBOX else super( SandboxEntity, self).doSelectAction(action) def getConfirmDialogMeta(self, ctx): if not self.hasLockedState() and not ctx.hasFlags( FUNCTIONAL_FLAG.TUTORIAL) and AccountSettings.getSettings( DEFAULT_QUEUE) == QUEUE_TYPE.SANDBOX: meta = rally_dialog_meta.createLeavePreQueueMeta( ctx, self.getQueueType(), self.canSwitch(ctx)) else: meta = super(SandboxEntity, self).getConfirmDialogMeta(ctx) return meta def _createActionsValidator(self): return SandboxActionsValidator(self) def _doQueue(self, ctx): BigWorld.player().enqueueSandbox(ctx.getVehicleInventoryID()) LOG_DEBUG('Sends request on queuing to the PvE tutorial battle', ctx) def _doDequeue(self, ctx): BigWorld.player().dequeueSandbox() LOG_DEBUG('Sends request on dequeuing from the PvE tutorial battle') def _makeQueueCtxByAction(self, action=None): invID = g_currentVehicle.invID if not invID: raise SoftException('Inventory ID of vehicle can not be zero') return SandboxQueueCtx(invID, waitingID='prebattle/join') def _goToQueueUI(self): g_eventDispatcher.loadSandboxQueue() return FUNCTIONAL_FLAG.LOAD_WINDOW def _exitFromQueueUI(self): g_eventDispatcher.unloadSandboxQueue() def __onServerSettingChanged(self, diff): if not self.lobbyContext.getServerSettings().isSandboxEnabled(): def __leave(_=True): g_prbCtrlEvents.onPreQueueLeft() if self.isInQueue(): self.dequeue(DequeueCtx(waitingID='prebattle/leave'), callback=__leave) else: __leave()
class GlobalVarsManager(GlobalVarsMgrMeta): _isLoginLoadInfoRequested = False itemsCache = dependency.descriptor(IItemsCache) wallet = dependency.descriptor(IWalletController) tradeIn = dependency.descriptor(ITradeInController) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(GlobalVarsManager, self).__init__() def isDevelopment(self): return constants.IS_DEVELOPMENT def isShowLangaugeBar(self): return GUI_SETTINGS.isShowLanguageBar def isShowServerStats(self): return constants.IS_SHOW_SERVER_STATS def isChina(self): return constants.IS_CHINA def isKorea(self): return constants.IS_KOREA def isTutorialRunning(self, tutorialID): try: from tutorial.loader import isTutorialRunning except: def isTutorialRunning(_): return False return isTutorialRunning(tutorialID) def isFreeXpToTankman(self): return self.itemsCache.items.shop.freeXPToTManXPRate > 0 def getLocaleOverride(self): return getClientOverride() def isRoamingEnabled(self): return self.lobbyContext.getServerSettings().roaming.isEnabled() def isInRoaming(self): return self.lobbyContext.getServerSettings().roaming.isInRoaming() def isWalletAvailable(self): if self.wallet: return self.wallet.isAvailable else: return False def isShowLoginRssFeed(self): return GUI_SETTINGS.loginRssFeed.show def isShowTicker(self): return constants.IS_CHINA and GUI_SETTINGS.movingText.show def isRentalsEnabled(self): return constants.IS_RENTALS_ENABLED def isPotapovQuestEnabled(self): return self.lobbyContext.getServerSettings().isPotapovQuestEnabled() def isLoginLoadedAtFirstTime(self): if GlobalVarsManager._isLoginLoadInfoRequested: return False else: GlobalVarsManager._isLoginLoadInfoRequested = True return True def isVehicleRestoreEnabled(self): return self.lobbyContext.getServerSettings().isVehicleRestoreEnabled() def isTradeInEnabled(self): return self.tradeIn.isEnabled() def isBootcampFinished(self): return g_bootcamp.isFinished()
class _NodeContainer(object): itemsCache = dependency.descriptor(IItemsCache) goodiesCache = dependency.descriptor(IGoodiesCache) def __init__(self, childCount, itemTypeOrGroup, nextNode=None): super(_NodeContainer, self).__init__() self._maxChildCount = childCount self._nextNode = nextNode self._children = [] self._itemTypeOrGroup = itemTypeOrGroup def getVO(self): items = [] self._sortChildren() for i, child in enumerate(self._children): items.append( _createItemVO(child, self.itemsCache, self.goodiesCache, i)) return self.wrapVO(items) def getNextNode(self): return self._nextNode def destroy(self): self._nextNode = None return def addItem(self, item, vehicle, vehicleGroupId): if _checkItemType( item.type, self._itemTypeOrGroup) and item.groupID == vehicleGroupId: slotIdx = len(self._children) if slotIdx < self._maxChildCount: mayInstall, counterLimit = self._install( item, vehicle, slotIdx) if mayInstall: itemsCount = item.count if counterLimit == _UNLIMITED_ITEMS_COUNT or itemsCount <= counterLimit: self._children.append(item) return self._children.append(item.replace({'count': counterLimit})) itemsLeft = itemsCount - counterLimit item = item.replace({'count': itemsLeft}) self._addItemToNextNode(item, vehicle, vehicleGroupId) @staticmethod def wrapVO(items): result = {} if items: result = { 'items': items, 'isEnabled': True, 'topTitle': '', 'topTitleSmall': '' } return result def _install(self, item, vehicle, slotIdx): for child in self._children: if child.id == item.id: return (False, 1) return (True, 1) def _addItemToNextNode(self, item, vehicle, vehicleGroupId): if self._nextNode: self._nextNode.addItem(item, vehicle, vehicleGroupId) def _sortChildren(self): pass
class QuestProgressController(IArenaPeriodController, IArenaVehiclesController): eventsCache = dependency.descriptor(IEventsCache) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(QuestProgressController, self).__init__() self._period = ARENA_PERIOD.IDLE self._endTime = 0 self._length = 0 self._callbackID = None self.__storage = {} self.__selectedQuest = None self.__eManager = EventManager() self.__battleCtx = None self.__isInited = False self.__inProgressQuests = {} self.onConditionProgressUpdate = Event(self.__eManager) self.onHeaderProgressesUpdate = Event(self.__eManager) self.onFullConditionsUpdate = Event(self.__eManager) self.onQuestProgressInited = Event(self.__eManager) return def getInProgressQuests(self): return self.__inProgressQuests def hasQuestsToPerform(self): return bool(self.__inProgressQuests) def getSelectedQuest(self): return self.__selectedQuest def isInited(self): return self.__isInited def selectQuest(self, missionID): self.__selectedQuest = self.__inProgressQuests.get(missionID) self.onFullConditionsUpdate() def invalidateArenaInfo(self): isPersonalMissionsEnabled = self.lobbyContext.getServerSettings( ).isPersonalMissionsEnabled if not self.__isInited: personalMissions = self.eventsCache.getPersonalMissions() selectedMissionsIDs = self.__battleCtx.getSelectedQuestIDs() selectedMissionsInfo = self.__battleCtx.getSelectedQuestInfo( ) or {} if selectedMissionsIDs: missions = personalMissions.getAllQuests() for missionID in selectedMissionsIDs: mission = missions.get(missionID) if mission and not mission.isDisabled( ) and isPersonalMissionsEnabled(mission.getQuestBranch()): pqState = selectedMissionsInfo.get( missionID, (0, PM_STATE.NONE))[1] mission.updatePqStateInBattle(pqState) self.__inProgressQuests[missionID] = mission if mission.hasBattleProgress(): generalQuestID = mission.getGeneralQuestID() self.__selectedQuest = mission self.__storage[ generalQuestID] = BattleProgressStorage( generalQuestID, mission.getConditionsConfig(), mission.getConditionsProgress()) if self.__selectedQuest is None: self.__selectedQuest = first( self.__inProgressQuests.itervalues()) self.__updateTimerConditions(sendDiff=False) self.__isInited = True self.onQuestProgressInited() return def startControl(self, battleCtx, arenaVisitor): self.__battleCtx = battleCtx def areQuestsEnabledForArena(self): return self.__battleCtx.areQuestsEnabledForArena() def stopControl(self): self._period = ARENA_PERIOD.IDLE self._endTime = 0 self._length = 0 self.__selectedQuest = None self.__battleCtx = None self.__storage.clear() self.__eManager.clear() self.__clearCallback() self.__inProgressQuests.clear() self.__isInited = False return def setPeriodInfo(self, period, endTime, length, additionalInfo, soundID): self.__updatePeriodInfo(period, endTime, length) def invalidatePeriodInfo(self, period, endTime, length, additionalInfo): self.__updatePeriodInfo(period, endTime, length) def getQuestFullData(self): selectedQuest = self.__selectedQuest if selectedQuest: formatter = self.__getFormatter(selectedQuest) return { 'questName': selectedQuest.getUserName(), 'questID': selectedQuest.getID(), 'questIndexStr': str(selectedQuest.getInternalID()), 'questIcon': RES_ICONS.getAllianceGoldIcon(selectedQuest.getMajorTag()), 'headerProgress': formatter.headerFormat(), 'bodyProgress': formatter.bodyFormat() } return {} def getQuestHeaderProgresses(self): formatter = self.__getFormatter(self.__selectedQuest) return formatter.headerFormat() def updateQuestProgress(self, questID, info): if questID in self.__storage: self.__storage[questID].update(info) else: _logger.error('Storage for quest:%s is not found.', questID) selectedQuest = self.__selectedQuest if selectedQuest is not None and selectedQuest.hasBattleProgress(): storage = self.__storage[selectedQuest.getGeneralQuestID()] needHeaderResync = False for headerProgress in storage.getHeaderProgresses().itervalues(): if headerProgress.isChanged(): needHeaderResync = True headerProgress.markAsVisited() if needHeaderResync: self.onHeaderProgressesUpdate() for progressID, condProgress in storage.getChangedConditions( ).iteritems(): condProgress.markAsVisited() self.onConditionProgressUpdate(progressID, condProgress.getProgress()) return def getControllerID(self): return BATTLE_CTRL_ID.QUEST_PROGRESS def getCtrlScope(self): return _SCOPE.PERIOD | _SCOPE.VEHICLES def __updatePeriodInfo(self, period, endTime, length): self._period = period self._endTime = endTime self._length = length self.__clearCallback() if self._period == ARENA_PERIOD.BATTLE: self.__setCallback() def __setCallback(self): self._callbackID = None battleEndLeftTime = self._endTime - BigWorld.serverTime() tickInterval = 1 if battleEndLeftTime > 1 else 0 self.__updateTimerConditions() self._callbackID = BigWorld.callback(tickInterval, self.__setCallback) return def __clearCallback(self): if self._callbackID is not None: BigWorld.cancelCallback(self._callbackID) self._callbackID = None return def __updateTimerConditions(self, sendDiff=True): selectedQuest = self.__selectedQuest hasProgress = selectedQuest and selectedQuest.hasBattleProgress() if self._period == ARENA_PERIOD.BATTLE and hasProgress: startTime = self._endTime - self._length timesGoneFromStart = BigWorld.serverTime() - startTime timerConditions = self.__storage[ selectedQuest.getGeneralQuestID()].getTimerConditions() for progressID, condProgress in timerConditions.iteritems(): secondsLeft = max( condProgress.getCountDown() - timesGoneFromStart, 0) isChanged = condProgress.setTimeLeft(secondsLeft) if isChanged and sendDiff: self.onConditionProgressUpdate(progressID, condProgress.getProgress()) def __getFormatter(self, selectedQuest): return DetailedProgressFormatter( self.__storage.get(selectedQuest.getGeneralQuestID()), selectedQuest) if selectedQuest.hasBattleProgress( ) else PM1BattleConditionsFormatterAdapter(selectedQuest)
class CarouselEnvironment(CarouselEnvironmentMeta, IGlobalListener, ICarouselEnvironment): rentals = dependency.descriptor(IRentalsController) igrCtrl = dependency.descriptor(IIGRController) clanLock = dependency.descriptor(IClanLockController) settingsCore = dependency.descriptor(ISettingsCore) itemsCache = dependency.descriptor(IItemsCache) epicController = dependency.descriptor(IEpicBattleMetaGameController) rankedController = dependency.descriptor(IRankedBattlesController) lobbyContext = dependency.descriptor(ILobbyContext) __battleSession = dependency.descriptor(IBattleSessionProvider) def __init__(self): super(CarouselEnvironment, self).__init__() self._usedFilters = self._getFilters() self._carouselDPConfig = { 'carouselFilter': None, 'itemsCache': None, 'currentVehicle': None } self._carouselDPCls = CarouselDataProvider self._carouselFilterCls = CarouselFilter self._carouselDP = None self._currentVehicle = None self.__filterPopoverRemoveCallback = None return def setPopoverCallback(self, callback=None): self.__filterPopoverRemoveCallback = callback def onPlayerStateChanged(self, entity, roster, accountInfo): if accountInfo.isCurrentPlayer(): self.updateAviability() def onUnitPlayerStateChanged(self, pInfo): if pInfo.isCurrentPlayer(): self.updateAviability() def onPrbEntitySwitched(self): self.updateAviability() def onEnqueued(self, queueType, *args): self.updateAviability() def onDequeued(self, queueType, *args): self.updateAviability() def onUnitAutoSearchStarted(self, timeLeft): self.updateAviability() def onUnitAutoSearchFinished(self): self.updateAviability() @property def filter(self): return self._carouselDP.filter if self._carouselDP is not None else None def getTotalVehiclesCount(self): return self._carouselDP.getTotalVehiclesCount() def getCurrentVehiclesCount(self): return self._carouselDP.getCurrentVehiclesCount() def hasRentedVehicles(self): return self._carouselDP.hasRentedVehicles() def hasEventVehicles(self): return self._carouselDP.hasEventVehicles() def resetFilters(self): self.filter.reset() self.applyFilter() def applyFilter(self): self._carouselDP.applyFilter() if not self.filter.isDefault(): drawAttention = self._carouselDP.getCurrentVehiclesCount() == 0 self.as_showCounterS(self.formatCountVehicles(), drawAttention) else: self.as_hideCounterS() def formatCountVehicles(self): return formatCountString(self._carouselDP.getCurrentVehiclesCount(), self._carouselDP.getTotalVehiclesCount()) def blinkCounter(self): self.as_blinkCounterS() def selectVehicle(self, idx): if self.__battleSession.isReplayPlaying: return self._carouselDP.selectVehicle(idx) def updateVehicles(self, vehicles=None, filterCriteria=None): if self._carouselDP is not None: self._carouselDP.updateVehicles(vehicles, filterCriteria) self.applyFilter() return def updateAviability(self): if not self.isDisposed(): state = self._currentVehicle.getViewState() self.as_setEnabledS(not state.isLocked()) def _populate(self): super(CarouselEnvironment, self)._populate() self._currentVehicle = g_currentVehicle self._initDataProvider() setting = self.settingsCore.options.getSetting( settings_constants.GAME.VEHICLE_CAROUSEL_STATS) self._carouselDP.setShowStats(setting.get()) self._carouselDP.setEnvironment(self.app) self._carouselDP.setFlashObject(self.as_getDataProviderS()) self._carouselDP.buildList() self.rentals.onRentChangeNotify += self.__updateRent self.igrCtrl.onIgrTypeChanged += self.__updateIgrType self.clanLock.onClanLockUpdate += self.__updateClanLocks self.itemsCache.onSyncCompleted += self.__onCacheResync self._currentVehicle.onChanged += self.__onCurrentVehicleChanged self.epicController.onUpdated += self.__updateEpicSeasonRent self.rankedController.onUpdated += self.__updateRankedBonusBattles self.settingsCore.onSettingsChanged += self._onCarouselSettingsChange self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingChanged g_playerEvents.onVehicleBecomeElite += self.__onVehicleBecomeElite g_prbCtrlEvents.onVehicleClientStateChanged += self.__onVehicleClientStateChanged self.startGlobalListening() self.applyFilter() self.updateAviability() self.as_setInitDataS({ 'counterCloseTooltip': makeTooltip('#tooltips:tanksFilter/counter/close/header', '#tooltips:tanksFilter/counter/close/body') }) def _dispose(self): self.rentals.onRentChangeNotify -= self.__updateRent self.igrCtrl.onIgrTypeChanged -= self.__updateIgrType self.clanLock.onClanLockUpdate -= self.__updateClanLocks self.itemsCache.onSyncCompleted -= self.__onCacheResync self._currentVehicle.onChanged -= self.__onCurrentVehicleChanged self.epicController.onUpdated -= self.__updateEpicSeasonRent self.rankedController.onUpdated -= self.__updateRankedBonusBattles self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingChanged self.settingsCore.onSettingsChanged -= self._onCarouselSettingsChange g_playerEvents.onVehicleBecomeElite -= self.__onVehicleBecomeElite g_prbCtrlEvents.onVehicleClientStateChanged -= self.__onVehicleClientStateChanged self.stopGlobalListening() self._currentVehicle = None self._carouselDP.fini() self._carouselDP = None self._carouselDPConfig.clear() self.__callPopoverCallback() super(CarouselEnvironment, self)._dispose() return def _initDataProvider(self): self._carouselDPConfig.update({ 'carouselFilter': self._carouselFilterCls(), 'itemsCache': self.itemsCache, 'currentVehicle': self._currentVehicle }) self._carouselDP = self._carouselDPCls(**self._carouselDPConfig) def _onCarouselSettingsChange(self, diff): if settings_constants.GAME.VEHICLE_CAROUSEL_STATS in diff: setting = self.settingsCore.options.getSetting( settings_constants.GAME.VEHICLE_CAROUSEL_STATS) self._carouselDP.setShowStats(setting.get()) self._carouselDP.updateVehicles() def __updateRent(self, vehicles): self.updateVehicles(vehicles) def __updateEpicSeasonRent(self, diff): self.updateVehicles(filterCriteria=REQ_CRITERIA.VEHICLE.SEASON_RENT) def __updateRankedBonusBattles(self): self.updateVehicles() def __updateIgrType(self, roomType, xpFactor): self.updateVehicles(filterCriteria=REQ_CRITERIA.VEHICLE.IS_PREMIUM_IGR) def __updateClanLocks(self, vehicles, isFull): if isFull: self.updateVehicles() else: self.updateVehicles(vehicles) def __onServerSettingChanged(self, diff): if 'crystal_rewards_config' in diff: self.updateVehicles() def __onCacheResync(self, reason, diff): if reason in (CACHE_SYNC_REASON.SHOP_RESYNC, CACHE_SYNC_REASON.DOSSIER_RESYNC): self.updateVehicles() self.updateAviability() return if reason in (CACHE_SYNC_REASON.STATS_RESYNC, CACHE_SYNC_REASON.INVENTORY_RESYNC, CACHE_SYNC_REASON.CLIENT_UPDATE): self.updateAviability() if GUI_ITEM_TYPE.VEHICLE in diff: self.updateVehicles(diff.get(GUI_ITEM_TYPE.VEHICLE)) def __onCurrentVehicleChanged(self): self.updateAviability() if self._carouselDP is not None: filteredIndex = self._carouselDP.findVehicleFilteredIndex( g_currentVehicle.item) if self._carouselDP.pyGetSelectedIdx() != filteredIndex: self._carouselDP.selectVehicle(filteredIndex) self._carouselDP.refresh() return def __onVehicleBecomeElite(self, *vehicles): self.updateVehicles(vehicles) def __onVehicleClientStateChanged(self, vehicles): self.updateVehicles(vehicles) def __callPopoverCallback(self): if callable(self.__filterPopoverRemoveCallback): callback = self.__filterPopoverRemoveCallback self.__filterPopoverRemoveCallback = None callback() return def _getFilters(self): return _CAROUSEL_FILTERS
class VehicleCompareCartPopover(VehicleCompareCartPopoverMeta): comparisonBasket = dependency.descriptor(IVehicleComparisonBasket) def remove(self, vehId): self.comparisonBasket.removeVehicleByIdx(int(vehId)) def removeAll(self): self.comparisonBasket.removeAllVehicles() def onWindowClose(self): self.destroy() def gotoCompareView(self): showVehicleCompare() self.destroy() def _populate(self): super(VehicleCompareCartPopover, self)._populate() self._cartDP = _VehicleCompareCartDataProvider() self._cartDP.setFlashObject(self.as_getDPS()) self._cartDP.rebuildList(self.comparisonBasket.getVehiclesCDs()) self.comparisonBasket.onChange += self.__onBasketChange self.comparisonBasket.onSwitchChange += self.__onVehCmpBasketStateChanged self.__initControls() def _dispose(self): super(VehicleCompareCartPopover, self)._dispose() self.comparisonBasket.onChange -= self.__onBasketChange self.comparisonBasket.onSwitchChange -= self.__onVehCmpBasketStateChanged self._cartDP.fini() self._cartDP = None return def __onVehCmpBasketStateChanged(self): if not self.comparisonBasket.isEnabled(): self.onWindowClose() else: self.__updateButtonsState() def __initControls(self): headers = [packHeaderColumnData('nationId', 49, 30, tooltip=VEH_COMPARE.CARTPOPOVER_SORTING_NATION, icon=RES_ICONS.MAPS_ICONS_FILTERS_NATIONS_ALL), packHeaderColumnData('typeIndex', 45, 30, tooltip=VEH_COMPARE.CARTPOPOVER_SORTING_VEHTYPE, icon=RES_ICONS.MAPS_ICONS_FILTERS_TANKS_ALL), packHeaderColumnData('level', 45, 30, tooltip=VEH_COMPARE.CARTPOPOVER_SORTING_VEHLVL, icon=RES_ICONS.MAPS_ICONS_BUTTONS_TAB_SORT_BUTTON_LEVEL), packHeaderColumnData('shortUserName', 140, 30, label=VEH_COMPARE.CARTPOPOVER_SORTING_VEHNAME, tooltip=VEH_COMPARE.CARTPOPOVER_SORTING_VEHNAME_TOOLTIP), packHeaderColumnData('actions', 1, 30)] self.as_setInitDataS({'title': text_styles.highTitle(_ms(VEH_COMPARE.CARTPOPOVER_TITLE)), 'tableHeaders': headers}) self.__updateButtonsState() def __onBasketChange(self, _): self.__updateButtonsState() def __updateButtonsState(self): count = self.comparisonBasket.getVehiclesCount() buttonsEnabled = count > 0 if self.comparisonBasket.isFull(): addBtnTT = VEH_COMPARE.CARTPOPOVER_FULLBASKETCMPBTN_TOOLTIP addBtnIcon = RES_ICONS.MAPS_ICONS_LIBRARY_ALERTICON else: addBtnTT = VEH_COMPARE.CARTPOPOVER_OPENCMPBTN_TOOLTIP addBtnIcon = None isNavigationEnabled = not g_prbLoader.getDispatcher().getFunctionalState().isNavigationDisabled() self.as_updateToCmpBtnPropsS({'btnLabel': _ms(VEH_COMPARE.CARTPOPOVER_GOTOCOMPAREBTN_LABEL, value=count), 'btnTooltip': addBtnTT, 'btnEnabled': buttonsEnabled and isNavigationEnabled, 'btnIcon': addBtnIcon}) isBasketLocked = self.comparisonBasket.isLocked self.as_updateClearBtnPropsS({'btnLabel': VEH_COMPARE.CARTPOPOVER_REMOVEALLBTN_LABEL, 'btnTooltip': VEH_COMPARE.CARTPOPOVER_REMOVEBTNLOCKED_TOOLTIP if isBasketLocked else VEH_COMPARE.CARTPOPOVER_REMOVEALLBTN_TOOLTIP, 'btnEnabled': buttonsEnabled and not isBasketLocked}) return
class VOIPManager(VOIPHandler): settingsCore = dependency.descriptor(ISettingsCore) def __init__(self): _logger.info('Create') super(VOIPManager, self).__init__() self.__initialized = False self.__enabled = False self.__enabledChannelID = None self.__voipServer = '' self.__voipDomain = '' self.__testDomain = '' self.__user = ['', ''] self.__channel = ['', ''] self.__currentChannel = '' self.__isChannelRejoin = False self.__inTesting = False self.__loggedIn = False self.__needLogginAfterInit = False self.__normalLogout = False self.__loginAttemptsRemained = 2 self.__fsm = VOIPFsm() self.__expBackOff = backoff.ExpBackoff(_BACK_OFF_MIN_DELAY, _BACK_OFF_MAX_DELAY, _BACK_OFF_MODIFIER, _BACK_OFF_EXP_RANDOM_FACTOR) self.__reLoginCallbackID = None self.__activateMicByVoice = False self.__captureDevices = [] self.__currentCaptureDevice = '' self.__channelUsers = {} self.onCaptureDevicesUpdated = Event.Event() self.onPlayerSpeaking = Event.Event() self.onInitialized = Event.Event() self.onFailedToConnect = Event.Event() self.onJoinedChannel = Event.Event() self.onLeftChannel = Event.Event() self.__fsm.onStateChanged += self.__onStateChanged return @proto_getter(PROTO_TYPE.BW_CHAT2) def bwProto(self): return None @storage_getter('users') def usersStorage(self): return None @proto_getter(PROTO_TYPE.MIGRATION) def proto(self): return None def destroy(self): self.__fsm.onStateChanged -= self.__onStateChanged self.__cancelReloginCallback() BigWorld.VOIP.finalise() _logger.info('Destroy') def isEnabled(self): return self.__enabled def isInitialized(self): return self.__initialized def isNotInitialized(self): return not self.__initialized and self.getState() == STATE.NONE def isInTesting(self): return self.__inTesting def getVOIPDomain(self): return self.__voipDomain def getCurrentChannel(self): return self.__currentChannel def isVoiceSupported(self): return self.getVOIPDomain() != '' and self.isInitialized() def isChannelAvailable(self): return True if self.bwProto.voipProvider.getChannelParams( )[0] else False def hasDesiredChannel(self): channelUrl = self.__channel[0] if channelUrl == self.__testDomain: return True currentChannelID = hash(channelUrl) return self.__enabledChannelID == currentChannelID def getUser(self): return self.__user[0] def isInDesiredChannel(self): if not self.__channel[0] == self.__currentChannel: return False if self.__currentChannel == self.__testDomain: return True currentChannelID = hash(self.__currentChannel) return self.__enabledChannelID == currentChannelID def getCaptureDevices(self): return self.__captureDevices def getCurrentCaptureDevice(self): return self.__currentCaptureDevice def getState(self): return self.__fsm.getState() def getAPI(self): return BigWorld.VOIP.getAPI() def isLoggedIn(self): return self.__loggedIn def onConnected(self): _logger.info('Subscribe') self.__loginAttemptsRemained = 2 voipEvents = g_messengerEvents.voip voipEvents.onChannelAvailable += self.__me_onChannelAvailable voipEvents.onChannelLost += self.__me_onChannelLost voipEvents.onCredentialReceived += self.__me_onCredentialReceived usersEvents = g_messengerEvents.users usersEvents.onUsersListReceived += self.__me_onUsersListReceived usersEvents.onUserActionReceived += self.__me_onUserActionReceived def onDisconnected(self): _logger.info('Unsubscribe') voipEvents = g_messengerEvents.voip voipEvents.onChannelAvailable -= self.__me_onChannelAvailable voipEvents.onChannelLost -= self.__me_onChannelLost voipEvents.onCredentialReceived -= self.__me_onCredentialReceived usersEvents = g_messengerEvents.users usersEvents.onUsersListReceived -= self.__me_onUsersListReceived usersEvents.onUserActionReceived -= self.__me_onUserActionReceived def enable(self, enabled, isInitFromPrefs=False): if enabled: self.__enable(isInitFromPrefs) else: dbIDs = set() for dbID, data in self.__channelUsers.iteritems(): if data['talking']: dbIDs.add(dbID) self.__disable() self.__fsm.update(self) def applyChannelSetting(self, isEnabled, channelID): self.__enabledChannelID = channelID if isEnabled else None self.__fsm.update(self) return def enableCurrentChannel(self, isEnabled=True, autoEnableVOIP=True): needsEnableVOIP = isEnabled and not self.settingsCore.getSetting( SOUND.VOIP_ENABLE) if autoEnableVOIP and needsEnableVOIP: self.settingsCore.applySetting(SOUND.VOIP_ENABLE, True) params = self.bwProto.voipProvider.getChannelParams() channelUrl = params[0] if channelUrl: _logger.debug( "VOIPManager.%s '%s'", 'EnableCurrentChannel' if isEnabled else 'DisabledCurrentChannel', channelUrl) channelID = hash(channelUrl) self.settingsCore.applySetting(SOUND.VOIP_ENABLE_CHANNEL, (isEnabled, channelID)) else: _logger.error( 'EnableCurrentChannel: Failed to enable channel. No channel available!' ) def isCurrentChannelEnabled(self): params = self.bwProto.voipProvider.getChannelParams() channelUrl = params[0] if channelUrl: channelID = hash(channelUrl) return self.__enabledChannelID == channelID return False def __enable(self, isInitFromPrefs): _logger.info('Enable') self.__enabled = True if self.__channel[0]: if not self.__user[0]: self.__requestCredentials() if not isInitFromPrefs: self.enableCurrentChannel(True) def __disable(self): _logger.info('Disable') self.__enabled = False def initialize(self, domain, server): if self.__initialized: _logger.warning('VOIPManager is already initialized') return _logger.info('Initialize') self.__voipServer = server self.__voipDomain = domain self.__testDomain = 'sip:confctl-2@' + self.__voipDomain _logger.debug("voip_server: '%s'", self.__voipServer) _logger.debug("voip_domain: '%s'", self.__voipDomain) _logger.debug("test_domain: '%s'", self.__testDomain) self.__fsm.update(self) logLevel = 0 section = Settings.g_instance.userPrefs if section.has_key('development'): section = section['development'] if section.has_key('vivoxLogLevel'): logLevel = section['vivoxLogLevel'].asInt vinit = { VOIPCommon.KEY_SERVER: 'http://%s/api2' % self.__voipServer, VOIPCommon.KEY_MIN_PORT: '0', VOIPCommon.KEY_MAX_PORT: '0', VOIPCommon.KEY_LOG_PREFIX: 'voip', VOIPCommon.KEY_LOG_SUFFIX: '.txt', VOIPCommon.KEY_LOG_FOLDER: '.', VOIPCommon.KEY_LOG_LEVEL: str(logLevel) } BigWorld.VOIP.initialise(vinit) def __login(self, name, password): if not self.__initialized: self.__needLogginAfterInit = True self.__user = [name, password] if not self.__needLogginAfterInit: self.__fsm.update(self) def __loginUser(self): _logger.info('Login Request: %s', self.__user[0]) cmd = {VOIPCommon.KEY_PARTICIPANT_PROPERTY_FREQUENCY: '100'} BigWorld.VOIP.login(self.__user[0], self.__user[1], cmd) def __loginUserOnCallback(self): self.__reLoginCallbackID = None self.__loginUser() return def __reloginUser(self): self.__loginAttemptsRemained -= 1 _logger.warning('VOIPHandler.ReloginUser. Attempts remained: %d', self.__loginAttemptsRemained) if self.__enabled: self.__requestCredentials(1) def __cancelReloginCallback(self): if self.__reLoginCallbackID is not None: BigWorld.cancelCallback(self.__reLoginCallbackID) self.__reLoginCallbackID = None return def __setReloginCallback(self): delay = self.__expBackOff.next() _logger.info('__setReloginCallback. Next attempt after %d seconds', delay) self.__reLoginCallbackID = BigWorld.callback( delay, self.__loginUserOnCallback) def logout(self): _logger.info('Logout') self.__clearUser() self.__clearDesiredChannel() self.__fsm.update(self) def __setAvailableChannel(self, channel, password): if not self.__initialized and self.__fsm.inNoneState(): self.initialize(self.__voipDomain, self.__voipServer) if not self.__user[0] and self.isEnabled(): self.__requestCredentials() _logger.info('ReceivedAvailableChannel: %s', channel) self.__channel = [channel, password] self.__fsm.update(self) self.__evaluateAutoJoinChannel(channel) def __evaluateAutoJoinChannel(self, newChannel): if newChannel == self.__testDomain: return _, channelID = self.settingsCore.getSetting(SOUND.VOIP_ENABLE_CHANNEL) newChannelID = hash(newChannel) if channelID != newChannelID: self.enableCurrentChannel(self.__isAutoJoinChannel(), autoEnableVOIP=False) def __joinChannel(self, channel, password): _logger.info("JoinChannel '%s'", channel) BigWorld.VOIP.joinChannel(channel, password) def __leaveChannel(self): if not self.__initialized: return _logger.info('LeaveChannel') self.__clearDesiredChannel() self.__fsm.update(self) def enterTestChannel(self): if self.__inTesting: return _logger.info('EnterTestChannel: %s', self.__testDomain) self.__inTesting = True self.__setAvailableChannel(self.__testDomain, '') def leaveTestChannel(self): if not self.__inTesting: return _logger.info('LeaveTestChannel') self.__inTesting = False params = self.bwProto.voipProvider.getChannelParams() if params[0]: self.__setAvailableChannel(*params) else: self.__leaveChannel() def setMasterVolume(self, attenuation): BigWorld.VOIP.setMasterVolume(attenuation) def setMicrophoneVolume(self, attenuation): BigWorld.VOIP.setMicrophoneVolume(attenuation) def __setVolume(self): self.setMasterVolume( int( round( SoundGroups.g_instance.getVolume( VOIPCommon.KEY_VOIP_MASTER) * 100))) self.setMicrophoneVolume( int( round( SoundGroups.g_instance.getVolume(VOIPCommon.KEY_VOIP_MIC) * 100))) def __muffleMasterVolume(self): SoundGroups.g_instance.muffleWWISEVolume() def __restoreMasterVolume(self): SoundGroups.g_instance.restoreWWISEVolume() def setVoiceActivation(self, enabled): _logger.debug('SetVoiceActivation: %s', str(enabled)) self.__activateMicByVoice = enabled self.setMicMute(not enabled) def setMicMute(self, muted=True): if not self.__initialized: return if muted and self.__activateMicByVoice: return self.__setMicMute(muted) def __setMicMute(self, muted): _logger.debug('SetMicMute: %s', str(muted)) if muted: BigWorld.VOIP.disableMicrophone() else: BigWorld.VOIP.enableMicrophone() def requestCaptureDevices(self): _logger.debug('RequestCaptureDevices') BigWorld.VOIP.getCaptureDevices() def setCaptureDevice(self, deviceName): _logger.info('SetCaptureDevice: %s', deviceName) BigWorld.VOIP.setCaptureDevice(deviceName) def isParticipantTalking(self, dbid): outcome = self.__channelUsers.get(dbid, {}).get('talking', False) return outcome def __requestCredentials(self, reset=0): _logger.info('RequestUserCredentials') self.bwProto.voipProvider.requestCredentials(reset) def __clearDesiredChannel(self): self.__channel = ['', ''] def __clearUser(self): self.__user = ['', ''] def __onChatActionMute(self, dbid, muted): _logger.debug('OnChatActionMute: dbID = %d, muted = %r', dbid, muted) if dbid in self.__channelUsers and self.__channelUsers[dbid][ 'muted'] != muted: self.__muteParticipantForMe(dbid, muted) def __muteParticipantForMe(self, dbid, mute): _logger.debug('MuteParticipantForMe: %d, %s', dbid, str(mute)) self.__channelUsers[dbid]['muted'] = mute uri = self.__channelUsers[dbid]['uri'] cmd = { VOIPCommon.KEY_COMMAND: VOIPCommon.CMD_SET_PARTICIPANT_MUTE, VOIPCommon.KEY_PARTICIPANT_URI: uri, VOIPCommon.KEY_STATE: str(mute) } BigWorld.VOIP.command(cmd) return True def __isAnyoneTalking(self): for info in self.__channelUsers.values(): if info['talking']: return True return False def __extractDBIDFromURI(self, uri): try: domain = self.__voipDomain login = uri.partition('sip:')[2].rpartition('@' + domain)[0] s = login[login.find('.') + 1:] return (int(s), login) except Exception: return -1 def __sendLeaveChannelCommand(self, channel): _logger.info('Leaving channel %s', channel) if channel: BigWorld.VOIP.leaveChannel(channel) self.__fsm.update(self) def __resetToInitializedState(self): _logger.debug('resetToInitializesState') if self.__currentChannel != '': for dbid in self.__channelUsers.iterkeys(): self.onPlayerSpeaking(dbid, False) self.__channelUsers.clear() self.__restoreMasterVolume() self.__currentChannel = '' if self.__needLogginAfterInit: self.__fsm.update(self) self.__needLogginAfterInit = False def __onStateChanged(self, _, newState): if newState == STATE.INITIALIZED: self.__resetToInitializedState() elif newState == STATE.LOGGING_IN: self.__loginUser() elif newState == STATE.LOGGED_IN: self.__fsm.update(self) elif newState == STATE.JOINING_CHANNEL: muteMic = self.__channel[ 0] != self.__testDomain and not self.__activateMicByVoice self.setMicMute(muteMic) self.__joinChannel(self.__channel[0], self.__channel[1]) elif newState == STATE.JOINED_CHANNEL: _logger.info('Joined to channel: %s', self.__currentChannel) self.__fsm.update(self) elif newState == STATE.LEAVING_CHANNEL: self.__sendLeaveChannelCommand(self.getCurrentChannel()) elif newState == STATE.LOGGING_OUT: self.__normalLogout = True BigWorld.VOIP.logout() def onVoipInited(self, data): _logger.debug('onVoipInited') returnCode = int(data[VOIPCommon.KEY_RETURN_CODE]) if returnCode == VOIPCommon.CODE_SUCCESS: self.__initialized = True self.__fsm.update(self) self.onInitialized(data) else: self.__initialized = False self.__fsm.reset() _logger.info('---------------------------') _logger.info("ERROR: '%d' - '%s'", int(data[VOIPCommon.KEY_STATUS_CODE]), data[VOIPCommon.KEY_STATUS_STRING]) _logger.info('---------------------------') def onVoipDestroyed(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Voip is not destroyed: %r', data) def onCaptureDevicesArrived(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Capture devices are not arrived: %r', data) return captureDevicesCount = int(data[VOIPCommon.KEY_COUNT]) self.__captureDevices = [] for i in xrange(captureDevicesCount): self.__captureDevices.append( str(data[VOIPCommon.KEY_CAPTURE_DEVICES + '_' + str(i)])) self.__currentCaptureDevice = str( data[VOIPCommon.KEY_CURRENT_CAPTURE_DEVICE]) self.onCaptureDevicesUpdated() def onSetCaptureDevice(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Capture device is not set: %r', data) def onSetLocalSpeakerVolume(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Local speaker volume is not set: %r', data) def onSetLocalMicVolume(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Local microphone volume is not set: %r', data) def onMuteLocalMic(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Local microphone volume is not muted: %r', data) def onLoginStateChange(self, data): returnCode = int(data[VOIPCommon.KEY_RETURN_CODE]) statusCode = int(data[VOIPCommon.KEY_STATUS_CODE]) statusString = data[VOIPCommon.KEY_STATUS_STRING] _logger.debug('onLoginStateChange: Return code %s', returnCode) if returnCode == VOIPCommon.CODE_SUCCESS: state = int(data[VOIPCommon.KEY_STATE]) _logger.debug('Return state %s', state) if state == VOIPCommon.STATE_LOGGED_IN: _logger.debug('onLoginStateChange: LOGGED IN') if self.getAPI() == VOIP_SUPPORTED_API.VIVOX: self.bwProto.voipProvider.logVivoxLogin() self.__loggedIn = True self.__expBackOff.reset() if self.__fsm.getState() == STATE.JOINED_CHANNEL: self.__joinChannel(self.__channel[0], self.__channel[1]) self.__fsm.update(self) elif state == VOIPCommon.STATE_LOGGED_OUT: _logger.debug('onLoginStateChange: LOGGED OUT %d - %s', statusCode, statusString) if self.__normalLogout: _logger.debug('onLoginStateChange: Normal logout') self.__normalLogout = False self.__loggedIn = False self.__fsm.update(self) elif self.__reLoginCallbackID is None: _logger.debug('onLoginStateChange: Network lost logout') self.__setReloginCallback() elif state == VOIPCommon.STATE_LOGGIN_OUT: _logger.debug('onLoginStateChange: LOGGING OUT %d - %s', statusCode, statusString) else: _logger.info('---------------------------') _logger.info("ERROR: '%d' - '%s'", statusCode, statusString) _logger.info('---------------------------') if (statusCode == VOIPCommon.STATUS_WRONG_CREDENTIALS or statusCode == VOIPCommon.STATUS_UNKNOWN_ACCOUNT ) and self.__loginAttemptsRemained > 0: self.__reloginUser() else: self.onFailedToConnect() return def onSessionAdded(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Session is not added: %r', data) return currentChannel = self.__currentChannel = data[VOIPCommon.KEY_URI] self.__setVolume() self.__fsm.update(self) isTestChannel = currentChannel == self.__testDomain self.onJoinedChannel(currentChannel, isTestChannel, self.__isChannelRejoin and not isTestChannel) def onSessionRemoved(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Session is not removed: %r', data) return for dbid in self.__channelUsers.iterkeys(): self.onPlayerSpeaking(dbid, False) self.__channelUsers.clear() self.__restoreMasterVolume() leftChannel = self.__currentChannel wasTest = leftChannel == self.__testDomain self.__currentChannel = '' self.__fsm.update(self) self.onLeftChannel(leftChannel, wasTest) def onNetworkTest(self, data): returnCode = int(data[VOIPCommon.KEY_RETURN_CODE]) if returnCode == VOIPCommon.CODE_ERROR: _logger.info('---------------------------') _logger.info("ERROR: '%d' - '%s'", int(data[VOIPCommon.KEY_STATUS_CODE]), data[VOIPCommon.KEY_STATUS_STRING]) _logger.info('---------------------------') self.onFailedToConnect() self.__clearDesiredChannel() self.__clearUser() def onParticipantAdded(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Participant is not added: %r', data) return uri = data[VOIPCommon.KEY_PARTICIPANT_URI] dbid, _ = self.__extractDBIDFromURI(uri) if dbid == -1: return self.__channelUsers[dbid] = { 'talking': False, 'uri': uri, 'muted': False } user = self.usersStorage.getUser(dbid) if user and user.isMuted(): self.__muteParticipantForMe(dbid, True) def onParticipantRemoved(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Participant is not removed: %r', data) return uri = data[VOIPCommon.KEY_PARTICIPANT_URI] dbid, _ = self.__extractDBIDFromURI(uri) if dbid in self.__channelUsers: del self.__channelUsers[dbid] self.onPlayerSpeaking(dbid, False) def onParticipantUpdated(self, data): if int(data[VOIPCommon.KEY_RETURN_CODE]) != VOIPCommon.CODE_SUCCESS: _logger.error('Participant is not updated: %r', data) return uri = data[VOIPCommon.KEY_PARTICIPANT_URI] dbid, _ = self.__extractDBIDFromURI(uri) if dbid == -1: return talking = int(data[VOIPCommon.KEY_IS_SPEAKING]) if dbid in self.__channelUsers: channelUser = self.__channelUsers[dbid] if channelUser['talking'] != talking: channelUser['talking'] = talking if self.__isAnyoneTalking(): self.__muffleMasterVolume() else: self.__restoreMasterVolume() self.onPlayerSpeaking(dbid, talking) @staticmethod def __isAutoJoinChannel(): if hasattr(BigWorld.player(), 'arena'): arena = BigWorld.player().arena return not (arena is not None and arena.guiType in (ARENA_GUI_TYPE.RANDOM, ARENA_GUI_TYPE.EPIC_RANDOM, ARENA_GUI_TYPE.EPIC_BATTLE)) else: return True def __me_onChannelAvailable(self, uri, pwd, isRejoin): self.__isChannelRejoin = isRejoin if not self.__inTesting: self.__setAvailableChannel(uri, pwd) def __me_onChannelLost(self): if not self.__inTesting: self.__leaveChannel() self.settingsCore.applySetting(SOUND.VOIP_ENABLE_CHANNEL, (False, 0)) def __me_onCredentialReceived(self, name, pwd): _logger.debug('OnUserCredentials: %s', name) self.__login(name, pwd) def __me_onUsersListReceived(self, tags): if USER_TAG.MUTED not in tags: return for user in self.usersStorage.getList(MutedFindCriteria()): dbID = user.getID() if dbID in self.__channelUsers: self.__muteParticipantForMe(dbID, True) def __me_onUserActionReceived(self, actionID, user, shadowMode): if actionID in (USER_ACTION_ID.MUTE_SET, USER_ACTION_ID.MUTE_UNSET): self.__onChatActionMute(user.getID(), user.isMuted())
class RankedBattlesView(LobbySubView, RankedBattlesViewMeta): __background_alpha__ = 0.5 itemsCache = dependency.descriptor(IItemsCache) rankedController = dependency.descriptor(IRankedBattlesController) def onEscapePress(self): self.__close() def onCloseBtnClick(self): self.__close() def onAwardClick(self, blockID): if blockID == _AWARD_BLOCK_IDS.WEB_LEAGUE: self.rankedController.openWebLeaguePage(ctx={ 'returnAlias': RANKEDBATTLES_ALIASES.RANKED_BATTLES_VIEW_ALIAS }) elif blockID == _AWARD_BLOCK_IDS.BOOBY_QUEST: consolationQuest = self.rankedController.getConsolationQuest() if consolationQuest is not None: showMissionDetails(missionID=consolationQuest.getID(), groupID=consolationQuest.getGroupID()) elif blockID == _AWARD_BLOCK_IDS.SEASON_AWARDS: g_eventBus.handleEvent(events.LoadViewEvent( RANKEDBATTLES_ALIASES.RANKED_BATTLES_CYCLES_VIEW_ALIAS), scope=EVENT_BUS_SCOPE.LOBBY) return def _populate(self): super(RankedBattlesView, self)._populate() self.rankedController.onUpdated += self.__updateData self.__updateData() def _dispose(self): self.rankedController.onUpdated -= self.__updateData super(RankedBattlesView, self)._dispose() def __setData(self, leagueData=None): self.as_setDataS({ 'header': text_styles.superPromoTitle(RANKED_BATTLES.RANKEDBATTLEVIEW_TITLE), 'closeLbl': RANKED_BATTLES.RANKEDBATTLEVIEW_CLOSEBTN, 'closeDescr': RANKED_BATTLES.RANKEDBATTLEVIEW_CLOSEBTNDESCR, 'playVideoLbl': RANKED_BATTLES.RANKEDBATTLEVIEW_PLAYVIDEOBTN, 'playVideoBtnEnabled': False, 'calendarStatus': self.__getStatusBlock(), 'progressBlock': self.__buildProgressData(), 'awardsBlock': self.__getAwardsBlock(leagueData), 'bgImgPath': RES_ICONS.MAPS_ICONS_RANKEDBATTLES_BG_RANK_BLUR, 'isUpdateProgress': False }) def __updateData(self): self.__setData() self.rankedController.getLeagueData()(self.__setData) def __updateProgress(self): self.as_setDataS({ 'progressBlock': self.__buildProgressData(), 'isUpdateProgress': True }) def __close(self): self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_HANGAR), scope=EVENT_BUS_SCOPE.LOBBY) self.destroy() def __getStatusBlock(self): status, timeLeft = self.rankedController.getPrimeTimeStatus() showPrimeTimeAlert = status != PRIME_TIME_STATUS.AVAILABLE return { 'alertIcon': RES_ICONS.MAPS_ICONS_LIBRARY_ALERTBIGICON if showPrimeTimeAlert else None, 'buttonIcon': RES_ICONS.MAPS_ICONS_BUTTONS_CALENDAR, 'buttonLabel': '', 'buttonVisible': True, 'buttonTooltip': makeTooltip( RANKED_BATTLES. RANKEDBATTLEVIEW_STATUSBLOCK_CALENDARBTNTOOLTIP_HEADER, RANKED_BATTLES. RANKEDBATTLEVIEW_STATUSBLOCK_CALENDARBTNTOOLTIP_BODY), 'statusText': self.__getAlertStatusText(timeLeft) if showPrimeTimeAlert else self.__getStatusText(), 'popoverAlias': RANKEDBATTLES_ALIASES.RANKED_BATTLES_CALENDAR_POPOVER, 'bgVisible': False, 'shadowFilterVisible': showPrimeTimeAlert } def __buildProgressData(self): if self.rankedController.isAccountMastered(): rank = self.rankedController.getCurrentRank() result = [ self.__packProgressInfo( RES_ICONS.MAPS_ICONS_RANKEDBATTLES_ICON_VICTORY, text_styles.vehicleName( _ms(RANKED_BATTLES. RANKEDBATTLEVIEW_PROGRESSBLOCK_FINALRANK))), self.__packRank(rank), self.__packProgressInfo( RES_ICONS.MAPS_ICONS_RANKEDBATTLES_ICON_FINAL_CUP_150X100, text_styles.vehicleName( _ms(RANKED_BATTLES. RANKEDBATTLEVIEW_PROGRESSBLOCK_CONTINUE))) ] else: result = [ self.__packRank(rank) for rank in self.rankedController.getRanksChain() if rank.getID() != 0 ] return result def __packRank(self, rank): isCurrent = rank.isCurrent() isFinal = isCurrent and rank.getID( ) == self.rankedController.getAccRanksTotal() bgImage = '' if isCurrent or isFinal: bgImage = RES_ICONS.MAPS_ICONS_RANKEDBATTLES_RANKEDBATTESVIEW_PIC_ICON_RANK_SHINE_364X364 imageSize = RANKEDBATTLES_ALIASES.WIDGET_SMALL if isCurrent: imageSize = RANKEDBATTLES_ALIASES.WIDGET_HUGE if isFinal else RANKEDBATTLES_ALIASES.WIDGET_BIG shieldStatus = self.rankedController.getShieldStatus( rank=rank, isStatic=True) if not isFinal else None return { 'linkage': 'RankUI', 'rankData': { 'rankVO': buildRankVO(rank, isEnabled=rank.isAcquired(), imageSize=imageSize, shieldStatus=shieldStatus, showShieldLabel=False, showLadderPoints=True), 'isBig': isCurrent or isFinal, 'isFinal': isFinal, 'imageBG': bgImage, 'description': '', 'isTransparent': not isCurrent, 'curIcon': '' } } def __packProgressInfo(self, image, description): return { 'linkage': 'ProgressInfoBlockUI', 'infoData': { 'image': image, 'description': description } } def __getStepsProgressSubBlock(self, completedSteps, totalSteps, showDescription=True): if showDescription: stepsStr = text_styles.stats(completedSteps) description = text_styles.main( _ms(RANKED_BATTLES.RANKEDBATTLEVIEW_PROGRESSBLOCK_STEPS, numbers='{} / {}'.format(stepsStr, totalSteps))) else: description = '' steps = [] for idx in xrange(1, totalSteps + 1): if idx <= completedSteps: steps.append( {'state': RANKEDBATTLES_ALIASES.STEP_RECEIVED_STATE}) else: steps.append( {'state': RANKEDBATTLES_ALIASES.STEP_NOT_RECEIVED_STATE}) return { 'linkage': 'StepsContainerUI', 'stepsData': { 'countText': description, 'nextCountText': '', 'steps': steps } } def __getAwardsBlock(self, leagueData=None): consolationQuest = self.rankedController.getConsolationQuest() consolationQuestBattlesLeft = None if consolationQuest is not None and not consolationQuest.isCompleted(): battlesCondition = consolationQuest.bonusCond.getConditions().find( 'battles') if battlesCondition is not None: progress = battlesCondition.getProgressPerGroup() if None in progress: currCount, total, _, _ = progress[None] consolationQuestBattlesLeft = total - currCount battlesPlayed = self.rankedController.getCurrentCycleStats( )['battlesCount'] return _AwardsBlockBuilder.pack(leagueData, consolationQuestBattlesLeft, battlesPlayed) def __getStatusText(self): season = self.rankedController.getCurrentSeason() endTimeStr = self.__getTillTimeString(season.getCycleEndDate()) key = RANKED_BATTLES.RANKEDBATTLEVIEW_STATUSBLOCK_STATUSTEXT return text_styles.stats(i18n.makeString(key)) + endTimeStr def __getAlertStatusText(self, timeLeft): timeLeftStr = time_utils.getTillTimeString( timeLeft, RANKED_BATTLES.STATUS_TIMELEFT) return text_styles.vehicleStatusCriticalText( _ms(RANKED_BATTLES.PRIMETIMEALERTMESSAGEBLOCK_MESSAGE, time=timeLeftStr)) def __getTillTimeString(self, endTime): timeDelta = time_utils.getTimeDeltaFromNow(endTime) if timeDelta > time_utils.ONE_DAY: formatter = text_styles.neutral else: formatter = text_styles.alert return formatter( time_utils.getTillTimeString(timeDelta, RANKED_BATTLES.STATUS_TIMELEFT))
class BattleRoyaleWebApi(W2CSchema): __battleRoyale = dependency.descriptor(IBattleRoyaleController) __itemsCache = dependency.descriptor(IItemsCache) @w2c(W2CSchema, name='get_calendar_info') def handleGetCalendarInfo(self, _): calendarData = dict() for season in self.__getSeasons(): if season is not None: calendarData['season'] = { 'id': season.getSeasonID(), 'start': season.getStartDate(), 'end': season.getEndDate() } calendarData['cycles'] = [{ 'id': cycle.ID, 'start': cycle.startDate, 'end': cycle.endDate, 'announce_only': cycle.announceOnly } for cycle in season.getAllCycles().values()] return calendarData @w2c(W2CSchema, name='get_seasons_achievements') def getSeasonAchievements(self, _): dossierDescr = self.__itemsCache.items.getAccountDossier( ).getDossierDescr() seasonsAchievements = self.__getSeasonAchievements( dossierDescr.expand('battleRoyaleSeasons'), BattleRoyaleSeasonAchievements) currentSeason = self.__battleRoyale.getCurrentSeason() if currentSeason and currentSeason.getCycleID(): now = time_utils.getCurrentLocalServerTimestamp() stats = self.__battleRoyale.getStats() seasonsAchievements[currentSeason.getSeasonID(), currentSeason.getCycleID()] = { 'battle_count': stats.battleCount, 'kill_count': stats.killCount, 'top1': stats.topCount, 'season_id': currentSeason.getSeasonID(), 'episode_id': currentSeason.getCycleID() or currentSeason.getLastActiveCycleID(now) } return seasonsAchievements.values() def __getSeasonAchievements(self, achievements, template): seasonsAchievements = {} for seasonID, cycleID in achievements: if not self.__validateSeasonData(seasonID, cycleID): continue key = (seasonID, cycleID) seasonsAchievements[key] = template( *(key + achievements[key]))._asdict() return seasonsAchievements def __validateSeasonData(self, seasonID, cycleID): seasons = self.__getSeasons() seasonValidationData = { season.getSeasonID(): [cycle.ID for cycle in season.getAllCycles().values()] for season in seasons if season is not None } return seasonID in seasonValidationData and cycleID in seasonValidationData.get( seasonID, []) def __getSeasons(self): return (self.__battleRoyale.getCurrentSeason(), self.__battleRoyale.getNextSeason(), self.__battleRoyale.getPreviousSeason())
class BattleTypeSelectPopover(BattleTypeSelectPopoverMeta): __rankedController = dependency.descriptor(IRankedBattlesController) __lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self, _=None): super(BattleTypeSelectPopover, self).__init__() self._tooltip = None return def selectFight(self, actionName): self.__selectFight(actionName) def getTooltipData(self, itemData, itemIsDisabled): if itemData is None: return else: tooltip = '' isSpecial = False if itemData == PREBATTLE_ACTION_NAME.RANDOM: tooltip = TOOLTIPS.BATTLETYPES_STANDART elif itemData == PREBATTLE_ACTION_NAME.EPIC: tooltip, isSpecial = self.__getEpicAvailabilityData() elif itemData == PREBATTLE_ACTION_NAME.RANKED: tooltip, isSpecial = self.__getRankedAvailabilityData() elif itemData == PREBATTLE_ACTION_NAME.E_SPORT: tooltip = TOOLTIPS.BATTLETYPES_UNIT elif itemData == PREBATTLE_ACTION_NAME.STRONGHOLDS_BATTLES_LIST: if not itemIsDisabled: tooltip = TOOLTIPS.BATTLETYPES_STRONGHOLDS else: tooltip = TOOLTIPS.BATTLETYPES_STRONGHOLDS_DISABLED elif itemData == PREBATTLE_ACTION_NAME.TRAININGS_LIST: tooltip = TOOLTIPS.BATTLETYPES_TRAINING elif itemData == PREBATTLE_ACTION_NAME.EPIC_TRAINING_LIST: tooltip = TOOLTIPS.BATTLETYPES_EPIC_TRAINING elif itemData == PREBATTLE_ACTION_NAME.SPEC_BATTLES_LIST: tooltip = TOOLTIPS.BATTLETYPES_SPEC elif itemData == PREBATTLE_ACTION_NAME.BATTLE_TUTORIAL: tooltip = TOOLTIPS.BATTLETYPES_BATTLETUTORIAL elif itemData == PREBATTLE_ACTION_NAME.SANDBOX: isSpecial = True tooltip = TOOLTIPS_CONSTANTS.BATTLE_TRAINING elif itemData == PREBATTLE_ACTION_NAME.BATTLE_ROYALE: tooltip = TOOLTIPS_CONSTANTS.BATTLE_ROYALE_SELECTOR_INFO isSpecial = True elif itemData == PREBATTLE_ACTION_NAME.MAPBOX: tooltip = TOOLTIPS_CONSTANTS.MAPBOX_SELECTOR_INFO isSpecial = True result = {'isSpecial': isSpecial, 'tooltip': tooltip} self._tooltip = tooltip return result def demoClick(self): demonstratorWindow = self.app.containerManager.getView( WindowLayer.WINDOW, criteria={ POP_UP_CRITERIA.VIEW_ALIAS: VIEW_ALIAS.DEMONSTRATOR_WINDOW }) if demonstratorWindow is not None: demonstratorWindow.onWindowClose() else: self.fireEvent( LoadViewEvent(SFViewLoadParams( VIEW_ALIAS.DEMONSTRATOR_WINDOW)), EVENT_BUS_SCOPE.LOBBY) return def update(self): if not self.isDisposed(): self.as_updateS(*battle_selector_items.getItems().getVOs()) def _populate(self): super(BattleTypeSelectPopover, self)._populate() self.update() def __getRankedAvailabilityData(self): return (TOOLTIPS_CONSTANTS.RANKED_SELECTOR_INFO, True) if self.__rankedController.isAvailable() else ( TOOLTIPS_CONSTANTS.RANKED_UNAVAILABLE_INFO, True) def __getEpicAvailabilityData(self): return (TOOLTIPS_CONSTANTS.EPIC_BATTLE_SELECTOR_INFO, True) @process def __selectFight(self, actionName): navigationPossible = yield self.__lobbyContext.isHeaderNavigationPossible( ) if not navigationPossible: return battle_selector_items.getItems().select(actionName)
class EpicMetaGameUnavailableTooltip(BlocksTooltipData): connectionMgr = dependency.descriptor(IConnectionManager) epicController = dependency.descriptor(IEpicBattleMetaGameController) def __init__(self, ctx): super(EpicMetaGameUnavailableTooltip, self).__init__(ctx, TOOLTIP_TYPE.EPIC_SELECTOR_UNAVAILABLE_INFO) self._setContentMargin(top=20, left=20, bottom=20, right=20) self._setMargins(afterBlock=20) self._setWidth(_TOOLTIP_MIN_WIDTH) def _packBlocks(self, *args): items = super(EpicMetaGameUnavailableTooltip, self)._packBlocks() items.append(self._packHeaderBlock()) timeTableBlocks = [self._packTimeTableHeaderBlock()] primeTime = self.epicController.getPrimeTimes().get( self.connectionMgr.peripheryID, None) if primeTime is None or self.epicController.hasAnySeason() is None: return items else: todayStart, todayEnd = time_utils.getDayTimeBoundsForLocal() todayEnd += 1 tomorrowStart, tomorrowEnd = todayStart + time_utils.ONE_DAY, todayEnd + time_utils.ONE_DAY todayPeriods = () tomorrowPeriods = () time, status = self.epicController.getSeasonEndTime() if status: todayPeriods = primeTime.getPeriodsBetween( todayStart, min(todayEnd, time)) if tomorrowStart < time: tomorrowPeriods = primeTime.getPeriodsBetween( tomorrowStart, min(tomorrowEnd, time)) todayStr = self._packPeriods(todayPeriods) timeTableBlocks.append( self._packTimeBlock(message=text_styles.main( EPIC_BATTLE. SELECTORTOOLTIP_EPICBATTLE_DISABLED_TIMETABLE_TODAY), timeStr=text_styles.bonusPreviewText( todayStr))) tomorrowStr = self._packPeriods(tomorrowPeriods) timeTableBlocks.append( self._packTimeBlock(message=text_styles.main( EPIC_BATTLE. SELECTORTOOLTIP_EPICBATTLE_DISABLED_TIMETABLE_TOMORROW ), timeStr=text_styles.stats( tomorrowStr))) items.append( formatters.packBuildUpBlockData( timeTableBlocks, 7, BLOCKS_TOOLTIP_TYPES. TOOLTIP_BUILDUP_BLOCK_WHITE_BG_LINKAGE)) items.append( self._getTillEndBlock( time_utils.getTimeDeltaFromNow( time_utils.makeLocalServerTime(time)))) return items def _packHeaderBlock(self): return formatters.packTitleDescBlock( title=text_styles.highTitle( EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_TITLE), desc=text_styles.main( EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_DESC)) def _packTimeTableHeaderBlock(self): return formatters.packImageTextBlockData( title=text_styles.stats( EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_TIMETABLE_TITLE ), img=RES_ICONS.MAPS_ICONS_BUTTONS_CALENDAR, imgPadding=formatters.packPadding(top=2), txtPadding=formatters.packPadding(left=5)) def _packTimeBlock(self, message, timeStr): return formatters.packTextParameterBlockData(value=timeStr, name=message, valueWidth=97) def _packPeriods(self, periods): if periods: periodsStr = [] for periodStart, periodEnd in periods: startTime = formatDate('%H:%M', periodStart) endTime = formatDate('%H:%M', periodEnd) periodsStr.append( i18n.makeString(RANKED_BATTLES.CALENDARDAY_TIME, start=startTime, end=endTime)) return '\n'.join(periodsStr) return i18n.makeString( EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_TIMETABLE_EMPTY) def _getTillEndBlock(self, timeLeft): _, status = self.epicController.getSeasonEndTime() if status: endKey = EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_TILLEND else: endKey = EPIC_BATTLE.SELECTORTOOLTIP_EPICBATTLE_DISABLED_STARTIN return formatters.packTextBlockData( text_styles.main(endKey) + ' ' + text_styles.stats( time_utils.getTillTimeString( timeLeft, MENU.HEADERBUTTONS_BATTLE_TYPES_RANKED_AVAILABILITY)))
class HitDirectionController(IViewComponentsController): __slots__ = ('__pull', '__ui', '__isVisible', '__callbackIDs', '__damageIndicatorCrits', '__damageIndicatorAllies', '__damageIndicatorExtType', '__arenaDP', '__weakref__') settingsCore = dependency.descriptor(ISettingsCore) sessionProvider = dependency.descriptor(IBattleSessionProvider) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self, setup): super(HitDirectionController, self).__init__() self.__pull = [ _HitDirection(idx_) for idx_ in xrange(HIT_INDICATOR_MAX_ON_SCREEN) ] self.__ui = None self.__isVisible = False self.__callbackIDs = {} self.__damageIndicatorExtType = False self.__damageIndicatorCrits = False self.__damageIndicatorAllies = False self.__arenaDP = weakref.proxy(setup.arenaDP) return def getControllerID(self): return BATTLE_CTRL_ID.HIT_DIRECTION def startControl(self): g_eventBus.addListener(GameEvent.GUI_VISIBILITY, self.__handleGUIVisibility, scope=EVENT_BUS_SCOPE.BATTLE) self.settingsCore.onSettingsChanged += self.__onSettingsChanged def stopControl(self): self.settingsCore.onSettingsChanged -= self.__onSettingsChanged handler = avatar_getter.getInputHandler() if handler is not None: from AvatarInputHandler import AvatarInputHandler if isinstance(handler, AvatarInputHandler): handler.onPostmortemKillerVisionEnter -= self.__onPostmortemKillerVision ctrl = self.sessionProvider.shared.vehicleState if ctrl is not None: ctrl.onVehicleControlling -= self.__onVehicleControlling g_eventBus.removeListener(GameEvent.GUI_VISIBILITY, self.__handleGUIVisibility, scope=EVENT_BUS_SCOPE.BATTLE) self.__clearHideCallbacks() self.__arenaDP = None return def getContainer(self): return self.__ui def getHit(self, idx): if idx < len(self.__pull): hit = self.__pull[idx] else: hit = None return hit def isVisible(self): return self.__isVisible def setVisible(self, flag): self.__isVisible = flag if self.__ui: self.__ui.setVisible(flag) def setViewComponents(self, component): self.__damageIndicatorExtType = bool( self.settingsCore.getSetting(DAMAGE_INDICATOR.TYPE)) self.__damageIndicatorCrits = bool( self.settingsCore.getSetting(DAMAGE_INDICATOR.PRESET_CRITS)) self.__damageIndicatorAllies = bool( self.settingsCore.getSetting(DAMAGE_INDICATOR.PRESET_ALLIES)) self.__ui = component self.__ui.invalidateSettings() self.__ui.setVisible(self.__isVisible) proxy = weakref.proxy(self.__ui) handler = avatar_getter.getInputHandler() if handler is not None: from AvatarInputHandler import AvatarInputHandler if isinstance(handler, AvatarInputHandler): handler.onPostmortemKillerVisionEnter += self.__onPostmortemKillerVision ctrl = self.sessionProvider.shared.vehicleState if ctrl is not None: ctrl.onVehicleControlling += self.__onVehicleControlling for hit in self.__pull: idx = hit.getIndex() duration = hit.setIndicator(proxy) if duration: self.__callbackIDs[idx] = BigWorld.callback( duration, partial(self.__tickToHideHit, idx)) return def clearViewComponents(self): for hit in self.__pull: hit.clear() if self.__ui: self.__ui.destroy() self.__ui = None return def addHit(self, hitDirYaw, attackerID, damage, isBlocked, critFlags, isHighExplosive, damagedID, attackReasonID): atackerVehInfo = self.__arenaDP.getVehicleInfo(attackerID) atackerVehType = atackerVehInfo.vehicleType isAlly = self.__arenaDP.isAllyTeam(atackerVehInfo.team) playerVehType = self.__arenaDP.getVehicleInfo(damagedID).vehicleType hitData = HitData(yaw=hitDirYaw, attackerID=attackerID, isAlly=isAlly, damage=damage, attackerVehName=atackerVehType.shortNameWithPrefix, isBlocked=isBlocked, attackerVehClassTag=atackerVehType.classTag, critFlags=critFlags, playerVehMaxHP=playerVehType.maxHealth, isHighExplosive=isHighExplosive, attackReasonID=attackReasonID, friendlyFireMode=self.__isFriendlyFireMode()) if not self._isValidHit(hitData): return else: hit = self.__findHit(hitData) if hit is None: extendHitData = False hit = self.__getNextHit() else: extendHitData = hit.isShown() idx = hit.getIndex() self.__clearHideCallback(idx) duration = hit.show(hitData, extend=extendHitData) if duration: self.__callbackIDs[idx] = BigWorld.callback( duration, partial(self.__tickToHideHit, idx)) return hit def _isValidHit(self, hitData): if hitData.isNonPlayerAttackReason( ) or hitData.isBattleAbilityConsumable( ) or hitData.isBattleConsumables(): return False isCriticalNoDamage = hitData.isCritical() and hitData.getDamage() == 0 if self.__damageIndicatorExtType and not self.__damageIndicatorCrits and isCriticalNoDamage: return False return False if self.__damageIndicatorExtType and not self.__damageIndicatorAllies and hitData.isFriendlyFire( ) else True def _hideAllHits(self): for hit in self.__pull: hit.hide() def __getNextHit(self): find = self.__pull[0] for hit in self.__pull: if not hit.isShown(): return hit if hit.getStartTime() < find.getStartTime(): find = hit return find def __isFriendlyFireMode(self): friendlyFireBonusTypes = self.lobbyContext.getServerSettings( ).getFriendlyFireBonusTypes() isFriendlyFireMode = self.sessionProvider.arenaVisitor.bonus.isFriendlyFireMode( friendlyFireBonusTypes) isCustomAllyDamageEffect = self.sessionProvider.arenaVisitor.bonus.hasCustomAllyDamageEffect( ) return isFriendlyFireMode and isCustomAllyDamageEffect def __findHit(self, hitData): for hit in self.__pull: data = hit.getHitData() if data is not None: if hitData.getAttackerID() == data.getAttackerID(): currentMask = data.getHitFlags() & _AGGREGATED_HIT_BITS newMask = hitData.getHitFlags() & _AGGREGATED_HIT_BITS if currentMask > 0: if currentMask == newMask: return hit if currentMask == HIT_FLAGS.HP_DAMAGE and newMask == HIT_FLAGS.HP_DAMAGE | HIT_FLAGS.IS_CRITICAL: return hit if currentMask == HIT_FLAGS.HP_DAMAGE | HIT_FLAGS.IS_CRITICAL and newMask == HIT_FLAGS.HP_DAMAGE: return hit return def __tickToHideHit(self, idx): self.__callbackIDs.pop(idx, None) self.__pull[idx].hide() return def __clearHideCallback(self, idx): callbackID = self.__callbackIDs.pop(idx, None) if callbackID is not None: BigWorld.cancelCallback(callbackID) return def __clearHideCallbacks(self): for _, callbackID in self.__callbackIDs.items(): if callbackID is not None: BigWorld.cancelCallback(callbackID) self.__callbackIDs.clear() return def __handleGUIVisibility(self, event): self.setVisible(event.ctx['visible']) def __onSettingsChanged(self, diff): if DAMAGE_INDICATOR.TYPE in diff: self.__damageIndicatorExtType = bool(diff[DAMAGE_INDICATOR.TYPE]) if DAMAGE_INDICATOR.PRESET_CRITS in diff: self.__damageIndicatorCrits = bool( diff[DAMAGE_INDICATOR.PRESET_CRITS]) if DAMAGE_INDICATOR.PRESET_ALLIES in diff: self.__damageIndicatorAllies = bool( diff[DAMAGE_INDICATOR.PRESET_ALLIES]) if self.__ui is not None: for key in _VISUAL_DAMAGE_INDICATOR_SETTINGS: if key in diff: self.__ui.invalidateSettings() for hit in self.__pull: hit.redraw() break return def __onPostmortemKillerVision(self, killerVehicleID): if killerVehicleID != self.__arenaDP.getPlayerVehicleID(): self._hideAllHits() def __onVehicleControlling(self, vehicle): if not vehicle.isPlayerVehicle: self._hideAllHits()
class CustomizationPropertiesSheet(CustomizationPropertiesSheetMeta): itemsCache = dependency.instance(IItemsCache) service = dependency.descriptor(ICustomizationService) _hangarSpace = dependency.descriptor(IHangarSpace) def __init__(self): super(CustomizationPropertiesSheet, self).__init__() self.__ctx = None self._slotID = -1 self._regionID = -1 self._areaID = -1 self._isVisible = False self._editMode = False self._extraMoney = None self._isItemAppliedToAll = False self.__interactionType = CUSTOMIZATION_ALIASES.CUSTOMIZATION_POJECTION_INTERACTION_DEFAULT self.__changes = [False] * 3 return @property def isVisible(self): return self._isVisible def editMode(self, value, interactionType): self._editMode = value if self._editMode: self.__interactionType = interactionType else: self.interactionStatusUpdate(False) self.__interactionType = -1 def interactionStatusUpdate(self, value): self.fireEvent( CameraRelatedEvents( CameraRelatedEvents.FORCE_DISABLE_CAMERA_MOVEMENT, ctx={'disable': value}), EVENT_BUS_SCOPE.DEFAULT) def setScale(self, value): pass def setRotation(self, value): pass def _populate(self): super(CustomizationPropertiesSheet, self)._populate() self.__ctx = self.service.getCtx() self._extraMoney = None self._isItemAppliedToAll = False self.__ctx.onCacheResync += self.__onCacheResync self.__ctx.onCustomizationSeasonChanged += self.__onSeasonChanged self.__ctx.onCustomizationItemInstalled += self.__onItemsInstalled self.__ctx.onCustomizationItemsRemoved += self.__onItemsRemoved self.__ctx.onCustomizationCamouflageColorChanged += self.__onCamouflageColorChanged self.__ctx.onCustomizationCamouflageScaleChanged += self.__onCamouflageScaleChanged self.__ctx.onCustomizationProjectionDecalScaleChanged += self.__onProjectionDecalScaleChanged self.__ctx.onCustomizationItemsBought += self.__onItemsBought self.__ctx.onCustomizationItemSold += self.__onItemSold return def _dispose(self): self.__ctx.onCustomizationItemSold -= self.__onItemSold self.__ctx.onCustomizationItemsBought -= self.__onItemsBought self.__ctx.onCustomizationCamouflageScaleChanged -= self.__onCamouflageScaleChanged self.__ctx.onCustomizationCamouflageColorChanged -= self.__onCamouflageColorChanged self.__ctx.onCustomizationProjectionDecalScaleChanged -= self.__onProjectionDecalScaleChanged self.__ctx.onCustomizationItemsRemoved -= self.__onItemsRemoved self.__ctx.onCustomizationItemInstalled -= self.__onItemsInstalled self.__ctx.onCustomizationSeasonChanged -= self.__onSeasonChanged self.__ctx.onCacheResync -= self.__onCacheResync self._extraMoney = None self._isItemAppliedToAll = False self._slotID = -1 self._regionID = -1 self._areaID = -1 self.__ctx = None super(CustomizationPropertiesSheet, self)._dispose() return def show(self, areaID, slotID, regionID): if self._slotID == slotID and self._regionID == regionID and self._areaID == areaID and self.isVisible: return self._slotID = slotID self._regionID = regionID self._areaID = areaID self._isVisible = True if self.__update(): self.__ctx.onPropertySheetShown() self.__ctx.vehicleAnchorsUpdater.displayMenu(True) def hide(self): if not self.isVisible: return self._isVisible = False self.as_hideS() self.__ctx.onPropertySheetHidden() self.__ctx.vehicleAnchorsUpdater.displayMenu(False) def onActionBtnClick(self, actionType, actionData): if actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_APPLY_TO_ALL_PARTS: self._isItemAppliedToAll = not self._isItemAppliedToAll self.__applyToOtherAreas(self._isItemAppliedToAll) elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_APPLY_TO_ALL_SEASONS: self._isItemAppliedToAll = not self._isItemAppliedToAll self.__applyToOtherSeasons(self._isItemAppliedToAll) elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_REMOVE_ONE: self.__removeElement() elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_RENT_CHECKBOX_CHANGE: self.__ctx.changeAutoRent() self.__update() elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_REMOVE_FROM_ALL_PARTS: self.__removeFromAllAreas() elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_SCALE_CHANGE: if self._slotID == GUI_ITEM_TYPE.CAMOUFLAGE: if self._currentComponent.patternSize != actionData: self.__ctx.changeCamouflageScale(self._areaID, self._regionID, actionData) elif self._slotID == GUI_ITEM_TYPE.PROJECTION_DECAL: actionData += 1 if self._currentComponent.scaleFactorId != actionData: self.__ctx.changeProjectionDecalScale( self._areaID, self._regionID, actionData) elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_COLOR_CHANGE: if self._currentComponent.palette != actionData: self.__ctx.changeCamouflageColor(self._areaID, self._regionID, actionData) elif actionType == CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_CLOSE: self.hide() self.__ctx.onClearItem() def onClose(self): self.hide() @property def _currentSlotData(self): if self._slotID == -1 or self._areaID == -1 or self._slotID == GUI_ITEM_TYPE.STYLE: return else: slot = self.__ctx.currentOutfit.getContainer(self._areaID).slotFor( self._slotID) if slot is None or self._regionID == -1: return slotId = self.__ctx.getSlotIdByAnchorId( C11nId(self._areaID, self._slotID, self._regionID)) return slot.getSlotData(slotId.regionIdx) @property def _currentItem(self): slotData = self._currentSlotData return None if slotData is None else slotData.item @property def _currentComponent(self): slotData = self._currentSlotData return None if slotData is None else slotData.component @property def _currentStyle(self): return self.__ctx.modifiedStyle if self._slotID == GUI_ITEM_TYPE.STYLE else None def __update(self): if self._isVisible and self._slotID != -1 and self._regionID != -1 and self._areaID != -1: self.__updateItemAppliedToAllFlag() self.__updateExtraPrice() self.as_setDataAndShowS(self.__makeVO()) self.__ctx.caruselItemUnselected() self.__ctx.onPropertySheetShown() return True return False def __applyToOtherAreas(self, installItem): if self.__ctx.currentTab not in (C11nTabs.PAINT, C11nTabs.CAMOUFLAGE): return currentSeason = self.__ctx.currentSeason if installItem: self.__ctx.installItemToAllTankAreas(currentSeason, self._slotID, self._currentSlotData) else: self.__ctx.removeItemFromAllTankAreas(currentSeason, self._slotID) self.__update() def __removeFromAllAreas(self): currentSeason = self.__ctx.currentSeason self.__ctx.removeItemFromAllTankAreas(currentSeason, self._slotID) self.__update() def __applyToOtherSeasons(self, installItem): if self.__ctx.currentTab not in (C11nTabs.EFFECT, C11nTabs.EMBLEM, C11nTabs.INSCRIPTION, C11nTabs.PROJECTION_DECAL): return if installItem: self.__ctx.installItemForAllSeasons(self._areaID, self._slotID, self._regionID, self._currentSlotData) else: self.__ctx.removeItemForAllSeasons(self._areaID, self._slotID, self._regionID) self.__update() def __removeElement(self): if self._slotID == GUI_ITEM_TYPE.STYLE: self.__ctx.removeStyle(self._currentStyle.intCD) else: slotId = self.__ctx.getSlotIdByAnchorId( C11nId(areaId=self._areaID, slotType=self._slotID, regionIdx=self._regionID)) if slotId is not None: self.__ctx.removeItemFromSlot(self.__ctx.currentSeason, slotId) return def __updateItemAppliedToAllFlag(self): self._isItemAppliedToAll = False if self.__ctx.currentTab in (C11nTabs.PAINT, C11nTabs.CAMOUFLAGE): self._isItemAppliedToAll = True for areaId in Area.TANK_PARTS: regionsIndexes = getAppliedRegionsForCurrentHangarVehicle( areaId, self._slotID) multiSlot = self.__ctx.currentOutfit.getContainer( areaId).slotFor(self._slotID) for regionIdx in regionsIndexes: slotData = multiSlot.getSlotData(regionIdx) df = self._currentSlotData.weakDiff(slotData) if slotData.item is None or df.item is not None: break else: continue self._isItemAppliedToAll = False break elif self.__ctx.currentTab in (C11nTabs.EFFECT, C11nTabs.EMBLEM, C11nTabs.INSCRIPTION): self._isItemAppliedToAll = True firstSeason = SeasonType.COMMON_SEASONS[0] fistSlotData = self.__ctx.getModifiedOutfit( firstSeason).getContainer(self._areaID).slotFor( self._slotID).getSlotData(self._regionID) if fistSlotData.item is not None: for season in SeasonType.COMMON_SEASONS[1:]: slotData = self.__ctx.getModifiedOutfit( season).getContainer(self._areaID).slotFor( self._slotID).getSlotData(self._regionID) df = fistSlotData.weakDiff(slotData) if slotData.item is None or df.item is not None: self._isItemAppliedToAll = False break else: self._isItemAppliedToAll = False return def __makeVO(self): currentElement = self._currentStyle if self._slotID == GUI_ITEM_TYPE.STYLE else self._currentItem vo = { 'intCD': -1 if not currentElement else currentElement.intCD, 'renderersData': self.__makeRenderersVOs() if currentElement else [], 'isProjectionEnable': self._slotID == GUI_ITEM_TYPE.PROJECTION_DECAL, 'isBigRadius': self._slotID in (GUI_ITEM_TYPE.INSCRIPTION, GUI_ITEM_TYPE.PROJECTION_DECAL, GUI_ITEM_TYPE.EMBLEM) } return vo def __makeSlotVO(self): vo = None if not self._currentItem: vo = { 'imgIconSrc': RES_ICONS.MAPS_ICONS_LIBRARY_TANKITEM_BUY_TANK_POPOVER_SMALL } return vo def __makeRenderersVOs(self): renderers = [] if self._slotID == GUI_ITEM_TYPE.PAINT: renderers.append(self.__makeSetOnOtherTankPartsRendererVO()) elif self._slotID == GUI_ITEM_TYPE.CAMOUFLAGE: vo = self.__makeCamoColorRendererVO() if vo is not None: renderers.append(vo) renderers.append(self.__makeScaleRendererVO()) renderers.append(self.__makeSetOnOtherTankPartsRendererVO()) elif self._slotID in (GUI_ITEM_TYPE.EMBLEM, GUI_ITEM_TYPE.INSCRIPTION, GUI_ITEM_TYPE.MODIFICATION): renderers.append(self.__makeSetOnOtherSeasonsRendererVO()) elif self._slotID == GUI_ITEM_TYPE.STYLE: isExtentionEnabled = self._currentStyle and self._currentStyle.isRentable if isExtentionEnabled: renderers.append(self.__makeExtensionRendererVO()) elif self._slotID == GUI_ITEM_TYPE.PROJECTION_DECAL: renderers.append(self.__makeScaleRendererVO()) renderers.append(self.__makeRemoveRendererVO()) renderers.append(self.__makeCloseeRendererVO()) return renderers def __updateExtraPrice(self): if self._isItemAppliedToAll and self._currentItem: appliedIems = tuple((it for it in self.__ctx.getPurchaseItems() if not it.isDismantling and it.item.intCD == self._currentItem.intCD)) if self.__ctx.currentTab in (C11nTabs.PAINT, C11nTabs.CAMOUFLAGE): appliedIems = tuple((it for it in appliedIems if it.group == self.__ctx.currentSeason)) outfit = self.__ctx.originalOutfit slotData = outfit.getContainer(self._areaID).slotFor( self._slotID).getSlotData(self._regionID) isCurrentlyApplied = slotData.item == self._currentItem itemCache = self.itemsCache.items.getItemByCD( self._currentItem.intCD) inventoryCount = itemCache.inventoryCount appliedItemPrice = itemCache.getBuyPrice() extraInventoryCount = max( 0, len(appliedIems) - max(inventoryCount, int(not isCurrentlyApplied))) self._extraMoney = appliedItemPrice.price * extraInventoryCount else: self._extraMoney = None return def __makeSetOnOtherTankPartsRendererVO(self): icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_TANK hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_TANK_HOVER actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_APPLYTOWHOLETANK if self._isItemAppliedToAll: icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_TANK hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_TANK_HOVER actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_CANCEL return { 'iconSrc': icon, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(actionBtnLabel), 'actionType': CUSTOMIZATION_ALIASES. CUSTOMIZATION_SHEET_ACTION_APPLY_TO_ALL_PARTS, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI } def __removeAllTankPartsRendererVO(self): icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_TANK hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_TANK_HOVER actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_CLEAR return { 'iconSrc': icon, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(actionBtnLabel), 'actionType': CUSTOMIZATION_ALIASES. CUSTOMIZATION_SHEET_ACTION_REMOVE_FROM_ALL_PARTS, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI } def __makeRemoveRendererVO(self): iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_CROSS hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_CROSS_HOVER if self._slotID == GUI_ITEM_TYPE.STYLE: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVESTYLE iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_STYLE_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_STYLE_X_HOVER else: if self._slotID == GUI_ITEM_TYPE.MODIFICATION: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVE_TANK iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EFFECTS_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EFFECTS_X_HOVER elif self._slotID == GUI_ITEM_TYPE.EMBLEM: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVE_EMBLEM iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EMBLEM_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EMBLEM_X_HOVER elif self._slotID == GUI_ITEM_TYPE.INSCRIPTION: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVE_INSCRIPTION iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_TYPE_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_TYPE_X_HOVER elif self._slotID == GUI_ITEM_TYPE.PROJECTION_DECAL: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVE_PROJECTIONDECAL iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EFFECTS_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_EFFECTS_X_HOVER else: actionBtnLabel = VEHICLE_CUSTOMIZATION.getSheetBtnRemoveText( getCustomizationTankPartName(self._areaID, self._regionID)) if self._slotID == GUI_ITEM_TYPE.CAMOUFLAGE: iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_CAMO_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_CAMO_X_HOVER elif self._slotID == GUI_ITEM_TYPE.PAINT: iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_COLORS_X hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_REMOVE_COLORS_X_HOVER return { 'iconSrc': iconSrc, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(actionBtnLabel), 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI, 'actionType': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_REMOVE_ONE } def __makeCloseeRendererVO(self): iconSrc = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_CROSS hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_CROSS_HOVER actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_CLOSE return { 'iconSrc': iconSrc, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(actionBtnLabel), 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI, 'actionType': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_CLOSE } def __makeExtensionRendererVO(self): if self.__ctx.autoRentEnabled(): icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_RENT hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_RENT_HOVER label = VEHICLE_CUSTOMIZATION.CUSTOMIZATION_POPOVER_STYLE_NOTAUTOPROLONGATIONLABEL else: icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_RENT hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_RENT_HOVER label = VEHICLE_CUSTOMIZATION.CUSTOMIZATION_POPOVER_STYLE_AUTOPROLONGATIONLABEL return { 'iconSrc': icon, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(label), 'actionType': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_RENT_CHECKBOX_CHANGE, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI } def __makeCamoColorRendererVO(self): btnsBlockVO = [] colornum = _DEFAULT_COLORNUM for palette in self._currentItem.palettes: colornum = max( colornum, sum( ((color >> 24) / 255.0 > 0 for color in palette))) for idx, palette in enumerate( islice(self._currentItem.palettes, _MAX_PALETTES)): texture = _PALETTE_TEXTURE.format(colornum=colornum) icon = camoIconTemplate(texture, _PALETTE_WIDTH, _PALETTE_HEIGHT, palette, background=_PALETTE_BACKGROUND) btnsBlockVO.append( CustomizationCamoSwatchVO( icon, idx == self._currentComponent.palette)._asdict()) return { 'iconSrc': RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_COLORS, 'iconHoverSrc': RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_COLORS_HOVER, 'actionType': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_COLOR_CHANGE, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_SCALE_COLOR_RENDERER_UI, 'btnsBlockVO': btnsBlockVO } if len(btnsBlockVO) == _MAX_PALETTES else None def __makeScaleRendererVO(self): btnsBlockVO = [] if self._slotID == GUI_ITEM_TYPE.CAMOUFLAGE: selected = self._currentComponent.patternSize else: selected = self._currentComponent.scaleFactorId - 1 for idx, scaleSizeLabel in enumerate(SCALE_SIZE): btnsBlockVO.append({ 'paletteIcon': '', 'label': scaleSizeLabel, 'selected': selected == idx, 'value': idx }) return { 'iconSrc': RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_SCALE, 'iconHoverSrc': RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_SCALE_HOVER, 'actionType': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_ACTION_SCALE_CHANGE, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_SCALE_COLOR_RENDERER_UI, 'btnsBlockVO': btnsBlockVO } def __makeSetOnOtherSeasonsRendererVO(self): icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_ALL_SEASON hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_ALL_SEASON_HOVER actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_APPLYTOALLMAPS if self._isItemAppliedToAll: actionBtnLabel = VEHICLE_CUSTOMIZATION.PROPERTYSHEET_ACTIONBTN_REMOVE_SEASONS icon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_ALL_SEASON hoverIcon = RES_ICONS.MAPS_ICONS_CUSTOMIZATION_PROPERTY_SHEET_ICON_DEL_ALL_SEASON_HOVER return { 'iconSrc': icon, 'iconHoverSrc': hoverIcon, 'actionBtnLabel': text_styles.tutorial(actionBtnLabel), 'actionType': CUSTOMIZATION_ALIASES. CUSTOMIZATION_SHEET_ACTION_APPLY_TO_ALL_SEASONS, 'rendererLnk': CUSTOMIZATION_ALIASES.CUSTOMIZATION_SHEET_BTN_RENDERER_UI } def __onCacheResync(self, *_): if not g_currentVehicle.isPresent(): self.hide() return if self.__ctx.mode == C11nMode.CUSTOM: self.hide() else: self.__update() def __onSeasonChanged(self, seasonType): self.hide() def __onCamouflageColorChanged(self, areaId, regionIdx, paletteIdx): self.__update() def __onCamouflageScaleChanged(self, areaId, regionIdx, scale): self.__update() def __onProjectionDecalScaleChanged(self, areaId, regionIdx, scale): self.__update() def __onItemsInstalled(self, item, slotId, buyLimitReached): self.__update() def __onItemsRemoved(self): self.hide() def __onItemsBought(self, purchaseItems, results): self.__update() def __onItemSold(self, item, count): self.__update()
class ProfileHof(ProfileHofMeta): _eventsCache = dependency.descriptor(IEventsCache) _clansController = dependency.descriptor(IWebController) _errorsStatusMap = { '1004': PROFILE_CONSTANTS.HOF_SPECIAL_CASES, '1005': PROFILE_CONSTANTS.HOF_SPECIAL_CASES, '1015': PROFILE_CONSTANTS.HOF_SPECIAL_CASES, '1016': PROFILE_CONSTANTS.HOF_SPECIAL_CASES, '1003': PROFILE_CONSTANTS.HOF_RESULTS_HIDE, '1006': PROFILE_CONSTANTS.HOF_RESULTS_EXCLUSION, '1007': PROFILE_CONSTANTS.HOF_RESULTS_INCLUSION } _requestRetriesCount = 3 _retryDelay = 0.5 _bgPath = '../maps/icons/hof/hof_back_landing.png' _buttonsWithCounter = (PROFILE_CONSTANTS.HOF_ACHIEVEMENTS_BUTTON, PROFILE_CONSTANTS.HOF_VEHICLES_BUTTON) def __init__(self, *args): super(ProfileHof, self).__init__(*args) self.__status = PROFILE_CONSTANTS.HOF_RESULTS_SHOW self.__retriesCount = 0 self.__isMaintenance = False self.__viewDisposed = False self.__requestProcessing = False self.__retryCallback = None return def showAchievementsRating(self): setHofButtonOld(PROFILE_CONSTANTS.HOF_ACHIEVEMENTS_BUTTON) self.__openHofBrowserView(getHofAchievementsRatingUrl()) def showVehiclesRating(self): setHofButtonOld(PROFILE_CONSTANTS.HOF_VEHICLES_BUTTON) self.__openHofBrowserView(getHofVehiclesRatingUrl()) @process def changeStatus(self): if self.__status == PROFILE_CONSTANTS.HOF_RESULTS_SHOW: success = yield DialogsInterface.showI18nConfirmDialog( 'hof/excludeRating') if success: self.__makeRequest( self._clansController.getClanDossier( ).requestHofUserExclude, PROFILE_CONSTANTS.HOF_RESULTS_EXCLUSION, lambda errorCode: self.__getRatingStatus()) elif self.__status == PROFILE_CONSTANTS.HOF_RESULTS_HIDE: self.__makeRequest( self._clansController.getClanDossier().requestHofUserRestore, PROFILE_CONSTANTS.HOF_RESULTS_INCLUSION, lambda errorCode: self.__getRatingStatus()) else: LOG_WARNING('Something went wrong! Getting actual status.') self.__getRatingStatus() def onSectionActivated(self): if self.lobbyContext.getServerSettings().bwHallOfFame.isStatusEnabled: if self.__requestProcessing: LOG_WARNING( 'ProfileHof request canceled: another request is processing' ) else: self.__getRatingStatus() else: self.as_setStatusS(PROFILE_CONSTANTS.HOF_SPECIAL_CASES) def _populate(self): super(ProfileHof, self)._populate() self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingChanged self.as_setBackgroundS(self._bgPath) self.as_setBtnCountersS(self.__getCountersList()) def _dispose(self): if self.__retryCallback: LOG_WARNING( 'ProfileHof request canceled: ProfileHof view was disposed') BigWorld.cancelCallback(self.__retryCallback) self.__viewDisposed = True self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingChanged super(ProfileHof, self)._dispose() def __getCountersList(self): counters = [] for buttonName in self._buttonsWithCounter: if isHofButtonNew(buttonName): counters.append({'componentId': buttonName, 'count': '1'}) return counters def __getRatingStatus(self): def handleError(errorCode): status = self._errorsStatusMap.get(errorCode) if status: self.__status = status self.as_setStatusS(status) else: LOG_ERROR('Unknown error code: ' + str(errorCode)) self.__makeRequest( self._clansController.getClanDossier().requestHofUserInfo, PROFILE_CONSTANTS.HOF_RESULTS_SHOW, handleError) @process def __makeRequest(self, requestFunc, successStatus, errorCallback): if self.__retriesCount == 0: if not self.__isMaintenance: self.as_showWaitingS(WAITING.HOF_LOADING) self.__requestProcessing = True else: self.__retryCallback = None response = yield requestFunc() if self.__viewDisposed: LOG_WARNING( 'ProfileHof request canceled: ProfileHof view was disposed') return else: if response: self.__refreshRequest() if self.__isMaintenance: self.as_hideServiceViewS() self.as_setBtnCountersS(self.__getCountersList()) self.__isMaintenance = False errors = response.getErrors() if not errors: self.__status = successStatus self.as_setStatusS(successStatus) else: errorCallback(errors[0]) elif self.__retriesCount < self._requestRetriesCount: self.__retriesCount += 1 self.__retryCallback = BigWorld.callback( self._retryDelay, partial(self.__makeRequest, requestFunc, successStatus, errorCallback)) else: self.__refreshRequest() if not self.__isMaintenance: self.__isMaintenance = True header = icons.alert() + i18n.makeString( MENU.BROWSER_DATAUNAVAILABLE_HEADER) description = i18n.makeString( MENU.BROWSER_DATAUNAVAILABLE_DESCRIPTION) self.as_showServiceViewS(header, description) self.as_setBtnCountersS([]) return def __refreshRequest(self): self.__retriesCount = 0 if not self.__isMaintenance: self.as_hideWaitingS() self.__requestProcessing = False def __openHofBrowserView(self, url): self._eventsCache.onProfileVisited() g_eventBus.handleEvent( events.LoadViewEvent(VIEW_ALIAS.BROWSER_VIEW, ctx={ 'url': url, 'returnAlias': VIEW_ALIAS.LOBBY_PROFILE, 'allowRightClick': True, 'webHandlers': createHofWebHandlers(), 'selectedAlias': VIEW_ALIAS.PROFILE_HOF, 'disabledKeys': getHofDisabledKeys(), 'onServerSettingsChange': onServerSettingsChange }), EVENT_BUS_SCOPE.LOBBY) def __onServerSettingChanged(self, diff): if 'hallOfFame' in diff: self.onSectionActivated()
class BCHangar(Hangar): bootcampCtrl = dependency.descriptor(IBootcampController) def __init__(self, ctx=None): super(BCHangar, self).__init__(ctx) self._observer = None return def showNewElements(self, newElements): list = newElements['keys'] if self._observer is not None: self._observer.as_showAnimatedS(list) self.ammoPanel.showNewElements(list) return def updateVisibleComponents(self, visibleSettings): if visibleSettings is None: visibleSettings = self.bootcampCtrl.getLobbySettings() if self._observer is not None: self._observer.as_setBootcampDataS(visibleSettings) self.ammoPanel.updateVisibleComponents(visibleSettings) self.headerComponent.updateVisibleComponents(visibleSettings) return def onEscape(self): dialogsContainer = self.app.containerManager.getContainer( ViewTypes.TOP_WINDOW) if not self.__isViewOpenOrLoading( dialogsContainer, VIEW_ALIAS.LOBBY_MENU) and not self.__isViewOpenOrLoading( dialogsContainer, VIEW_ALIAS.BOOTCAMP_OUTRO_VIDEO ) and not self.__isViewOpenOrLoading( dialogsContainer, VIEW_ALIAS.BOOTCAMP_QUEUE_DIALOG): self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_MENU), scope=EVENT_BUS_SCOPE.LOBBY) def showHelpLayout(self): pass def _onPopulateEnd(self): g_bootcampEvents.onRequestChangeResearchButtonState += self.researchPanel.setNavigationEnabled def _populate(self): super(BCHangar, self)._populate() self._observer = self.app.bootcampManager.getObserver( 'BCHangarObserver') if self._observer is not None: self._observer.as_setBootcampDataS( self.bootcampCtrl.getLobbySettings()) return def _dispose(self): g_bootcampEvents.onRequestChangeResearchButtonState -= self.researchPanel.setNavigationEnabled g_bootcampEvents.onHangarDispose() self._observer = None super(BCHangar, self)._dispose() return def __isViewOpenOrLoading(self, container, viewAlias): openView = container.getView( criteria={POP_UP_CRITERIA.VIEW_ALIAS: viewAlias}) if openView is not None: return True else: for loadingView in container.getAllLoadingViews(): if loadingView.settings.alias == viewAlias: return True return False
class SelectRespawnView(ViewImpl): __sessionProvider = dependency.descriptor(IBattleSessionProvider) def __init__(self, *args, **kwargs): super(SelectRespawnView, self).__init__( R.views.battle.battleRoyale.select_respawn.SelectRespawn(), ViewFlags.COMPONENT, SelectRespawnViewModel, *args, **kwargs) arenaVisitor = self.__sessionProvider.arenaVisitor self.__mapTexture = 'url:../../{}'.format( arenaVisitor.type.getMinimapTexture()) self.__background = self.__getBgByGeometryName( arenaVisitor.type.getGeometryName()) bottomLeft, topRight = arenaVisitor.type.getBoundingBox() self.__mapSize, _ = topRight - bottomLeft self.__offset = bottomLeft self.__closeTime = 0 self.__points = [] self.__pointsById = {} self.__timer = BRPrebattleTimer(weakref.proxy(self)) @property def viewModel(self): return super(SelectRespawnView, self).getViewModel() def updateCloseTime(self, timeLeft, state): self.__timer.updateCloseTime(timeLeft, state) def dispose(self): pass def setPoints(self, points): with self.viewModel.transaction() as vm: vmPoints = vm.getPoints() vmPoints.clear() for point in points: pointId = point['guid'] coordX, coordY = point['position'] - self.__offset pointVM = RespawnPointViewModel() pointVM.setPointID(pointId) pointVM.setCoordX(coordX) pointVM.setCoordY(coordY) vmPoints.addViewModel(pointVM) vmPoints.invalidate() def updatePoint(self, vehicleId, pointId, prevPointId): arenaDP = self.__sessionProvider.getArenaDP() playerName = arenaDP.getVehicleInfo(vehicleId).player.name with self.viewModel.transaction() as vm: vmPoints = vm.getPoints() for vmPoint in vmPoints: if vmPoint.getPointID() == pointId: if not vmPoint.getPlayerName1(): vmPoint.setPlayerName1(playerName) else: vmPoint.setPlayerName2(playerName) if vmPoint.getPointID() == prevPointId: if vmPoint.getPlayerName1() == playerName: vmPoint.setPlayerName1(vmPoint.getPlayerName2() or '') vmPoint.setPlayerName2('') if vmPoint.getPlayerName2() == playerName: vmPoint.setPlayerName2('') vmPoints.invalidate() def _initialize(self, *args, **kwargs): super(SelectRespawnView, self)._initialize() self.viewModel.onCompleteBtnClick += self.__onCompleteBtnClick self.viewModel.onSelectPoint += self.__onSelectPoint with self.viewModel.transaction() as vm: vm.setMapSize(abs(self.__mapSize)) vm.setMinimapBG(self.__mapTexture) vm.setHeader(R.strings.battle_royale.selectRespawn.header()) vm.setDescription( R.strings.battle_royale.selectRespawn.description()) vm.setBtnDescription( R.strings.battle_royale.selectRespawn.btnDescription()) vm.setBackground(self.__background) vm.setIsReplay(self.__sessionProvider.isReplayPlaying) def _finalize(self): super(SelectRespawnView, self)._finalize() self.viewModel.onCompleteBtnClick -= self.__onCompleteBtnClick self.viewModel.onSelectPoint -= self.__onSelectPoint def __getBgByGeometryName(self, geometry): if geometry == '250_br_battle_city2-1': return R.images.gui.maps.icons.battleRoyale.spawnBg.c_250_br_battle_city2_1( ) else: return R.images.gui.maps.icons.battleRoyale.spawnBg.c_251_br_battle_city3( ) if geometry == '251_br_battle_city3' else None def __onSelectPoint(self): spawnCtrl = self.__sessionProvider.dynamic.spawn if spawnCtrl: _logger.info('Selected point ID = %s', self.viewModel.getSelectedPointID()) spawnCtrl.chooseSpawnKeyPoint(self.viewModel.getSelectedPointID()) def __onCompleteBtnClick(self): spawnCtrl = self.__sessionProvider.dynamic.spawn if spawnCtrl: spawnCtrl.placeVehicle()
class ItemsRequester(IItemsRequester): itemsFactory = dependency.descriptor(IGuiItemsFactory) def __init__(self, inventory, stats, dossiers, goodies, shop, recycleBin, vehicleRotation, ranked, badges, epicMetaGame): self.__inventory = inventory self.__stats = stats self.__dossiers = dossiers self.__goodies = goodies self.__shop = shop self.__vehicleRotation = vehicleRotation self.__recycleBin = recycleBin self.__ranked = ranked self.__badges = badges self.__epicMetaGame = epicMetaGame self.__itemsCache = defaultdict(dict) self.__vehCustomStateCache = defaultdict(dict) @property def inventory(self): return self.__inventory @property def stats(self): return self.__stats @property def dossiers(self): return self.__dossiers @property def goodies(self): return self.__goodies @property def shop(self): return self.__shop @property def recycleBin(self): return self.__recycleBin @property def vehicleRotation(self): return self.__vehicleRotation @property def ranked(self): return self.__ranked @property def badges(self): return self.__badges @property def epicMetaGame(self): return self.__epicMetaGame @async @process def request(self, callback=None): from gui.Scaleform.Waiting import Waiting Waiting.show('download/inventory') yield self.__stats.request() yield self.__inventory.request() yield self.__vehicleRotation.request() Waiting.hide('download/inventory') Waiting.show('download/shop') yield self.__shop.request() Waiting.hide('download/shop') Waiting.show('download/dossier') yield self.__dossiers.request() Waiting.hide('download/dossier') Waiting.show('download/discounts') yield self.__goodies.request() Waiting.hide('download/discounts') Waiting.show('download/recycleBin') yield self.__recycleBin.request() Waiting.hide('download/recycleBin') Waiting.show('download/ranked') yield self.__ranked.request() Waiting.hide('download/ranked') Waiting.show('download/badges') yield self.__badges.request() Waiting.hide('download/badges') Waiting.show('download/epicMetaGame') yield self.epicMetaGame.request() Waiting.hide('download/epicMetaGame') callback(self) def isSynced(self): return self.__stats.isSynced() and self.__inventory.isSynced() and self.__recycleBin.isSynced() and self.__shop.isSynced() and self.__dossiers.isSynced() and self.__goodies.isSynced() and self.__vehicleRotation.isSynced() and self.ranked.isSynced() and self.epicMetaGame.isSynced() @async @process def requestUserDossier(self, databaseID, callback): dr = self.__dossiers.getUserDossierRequester(databaseID) userAccDossier = yield dr.getAccountDossier() clanInfo = yield dr.getClanInfo() seasons = yield dr.getRated7x7Seasons() ranked = yield dr.getRankedInfo() container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER] container[databaseID] = (userAccDossier, clanInfo, seasons, ranked) callback((userAccDossier, clanInfo, dr.isHidden)) def unloadUserDossier(self, databaseID): container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER] if databaseID in container: del container[databaseID] self.__dossiers.closeUserDossier(databaseID) @async @process def requestUserVehicleDossier(self, databaseID, vehTypeCompDescr, callback): dr = self.__dossiers.getUserDossierRequester(databaseID) userVehDossier = yield dr.getVehicleDossier(vehTypeCompDescr) container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER] container[databaseID, vehTypeCompDescr] = userVehDossier callback(userVehDossier) def clear(self): while self.__itemsCache: _, cache = self.__itemsCache.popitem() cache.clear() self.__vehCustomStateCache.clear() self.__inventory.clear() self.__shop.clear() self.__stats.clear() self.__dossiers.clear() self.__goodies.clear() self.__vehicleRotation.clear() self.__recycleBin.clear() self.__ranked.clear() self.__badges.clear() self.epicMetaGame.clear() def invalidateCache(self, diff=None): invalidate = defaultdict(set) if diff is None: LOG_DEBUG('Gui items cache full invalidation') for itemTypeID, cache in self.__itemsCache.iteritems(): if itemTypeID not in (GUI_ITEM_TYPE.ACCOUNT_DOSSIER, GUI_ITEM_TYPE.VEHICLE_DOSSIER, GUI_ITEM_TYPE.BATTLE_ABILITY): cache.clear() else: for statName, data in diff.get('stats', {}).iteritems(): if statName in ('unlocks', ('unlocks', '_r')): self._invalidateUnlocks(data, invalidate) if statName == 'eliteVehicles': invalidate[GUI_ITEM_TYPE.VEHICLE].update(data) if statName in ('vehTypeXP', 'vehTypeLocks'): invalidate[GUI_ITEM_TYPE.VEHICLE].update(data.keys()) if statName in (('multipliedXPVehs', '_r'),): getter = vehicles.getVehicleTypeCompactDescr inventoryVehiclesCDs = [ getter(v['compDescr']) for v in self.__inventory.getItems(GUI_ITEM_TYPE.VEHICLE).itervalues() ] invalidate[GUI_ITEM_TYPE.VEHICLE].update(inventoryVehiclesCDs) if statName in ('oldVehInvIDs',): invalidate[GUI_ITEM_TYPE.VEHICLE].update(data) for cacheType, data in diff.get('cache', {}).iteritems(): if cacheType == 'vehsLock': for itemID in data.keys(): vehData = self.__inventory.getVehicleData(_getDiffID(itemID)) if vehData is not None: invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehData.descriptor.type.compactDescr) for cacheType, data in diff.get('groupLocks', {}).iteritems(): if cacheType in ('isGroupLocked', 'groupBattles'): getter = vehicles.getVehicleTypeCompactDescr inventoryVehiclesCDs = [ getter(v['compDescr']) for v in self.inventory.getItems(GUI_ITEM_TYPE.VEHICLE).itervalues() ] invalidate[GUI_ITEM_TYPE.VEHICLE].update(inventoryVehiclesCDs) for itemTypeID, itemsDiff in diff.get('inventory', {}).iteritems(): if itemTypeID == GUI_ITEM_TYPE.VEHICLE: if 'compDescr' in itemsDiff: for strCD in itemsDiff['compDescr'].itervalues(): if strCD is not None: invalidate[itemTypeID].add(vehicles.getVehicleTypeCompactDescr(strCD)) for data in itemsDiff.itervalues(): for itemID in data.iterkeys(): vehData = self.__inventory.getVehicleData(_getDiffID(itemID)) if vehData is not None: invalidate[itemTypeID].add(vehData.descriptor.type.compactDescr) invalidate[GUI_ITEM_TYPE.TANKMAN].update(self.__getTankmenIDsForVehicle(vehData)) if itemTypeID == GUI_ITEM_TYPE.TANKMAN: for data in itemsDiff.itervalues(): invalidate[itemTypeID].update(data.keys()) for itemID in data.keys(): tmanInvID = _getDiffID(itemID) tmanData = self.__inventory.getTankmanData(tmanInvID) if tmanData is not None and tmanData.vehicle != -1: invalidate[GUI_ITEM_TYPE.VEHICLE].update(self.__getVehicleCDForTankman(tmanData)) invalidate[GUI_ITEM_TYPE.TANKMAN].update(self.__getTankmenIDsForTankman(tmanData)) if itemTypeID == GUI_ITEM_TYPE.SHELL: invalidate[itemTypeID].update(itemsDiff.keys()) vehicleItems = self.__inventory.getItems(GUI_ITEM_TYPE.VEHICLE) if vehicleItems: for shellIntCD in itemsDiff.iterkeys(): for vehicle in vehicleItems.itervalues(): shells = vehicle['shells'] for intCD, _, _ in LayoutIterator(shells): if shellIntCD == intCD: vehicleIntCD = vehicles.getVehicleTypeCompactDescr(vehicle['compDescr']) invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehicleIntCD) vehicleData = self.__inventory.getItemData(vehicleIntCD) if vehicleData is not None: gunIntCD = vehicleData.descriptor.gun.compactDescr invalidate[GUI_ITEM_TYPE.GUN].add(gunIntCD) if itemTypeID == GUI_ITEM_TYPE.CUSTOMIZATION: for vehicleIntCD, outfitsData in itemsDiff.get(CustomizationInvData.OUTFITS, {}).iteritems(): invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehicleIntCD) seasons = (outfitsData or {}).keys() or SeasonType.RANGE vehicle = self.getItemByCD(vehicleIntCD) for season in seasons: outfitCompactDescr = None if outfitsData: outfitData = outfitsData.get(season) if outfitData: outfitCompactDescr, _ = outfitData newOutfit = Outfit(outfitCompactDescr) if season == SeasonType.ALL: prevOutfit = vehicle.getOutfit(SeasonType.SUMMER) or Outfit() prevStyleId = prevOutfit.id newStyleId = newOutfit.id if prevStyleId != newStyleId: invalidStyles = set() invalidStyles.add(self.__updateStyleAppliedCount(prevStyleId, vehicleIntCD, 0)) invalidStyles.add(self.__updateStyleAppliedCount(newStyleId, vehicleIntCD, 1)) for styleIntCD in invalidStyles: if styleIntCD is not None: invalidate[GUI_ITEM_TYPE.CUSTOMIZATION].add(styleIntCD) else: prevOutfit = vehicle.getCustomOutfit(season) or Outfit() prevItemsCounter = prevOutfit.itemsCounter newItemsCounter = newOutfit.itemsCounter newItemsCounter.subtract(prevItemsCounter) for itemCD, count in newItemsCounter.iteritems(): self.__inventory.updateC11nItemAppliedCount(itemCD, vehicleIntCD, count) invalidate[GUI_ITEM_TYPE.CUSTOMIZATION].add(itemCD) invalidate[GUI_ITEM_TYPE.OUTFIT].add((vehicleIntCD, season)) for cType, items in itemsDiff.get(CustomizationInvData.ITEMS, {}).iteritems(): for idx in items.iterkeys(): intCD = vehicles.makeIntCompactDescrByID('customizationItem', cType, idx) invalidate[GUI_ITEM_TYPE.CUSTOMIZATION].add(intCD) invalidate[itemTypeID].update(itemsDiff.keys()) for itemType, itemsDiff in diff.get('recycleBin', {}).iteritems(): deletedItems = itemsDiff.get('buffer', {}) for itemID in deletedItems.iterkeys(): if itemType == 'tankmen': invalidate[GUI_ITEM_TYPE.TANKMAN].add(itemID * -1) invalidate[GUI_ITEM_TYPE.VEHICLE].add(itemID) if 'goodies' in diff: vehicleDiscounts = self.__shop.getVehicleDiscountDescriptions() for goodieID in diff['goodies'].iterkeys(): if goodieID in vehicleDiscounts: vehicleDiscount = vehicleDiscounts[goodieID] invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehicleDiscount.target.targetValue) for itemTypeID, uniqueIDs in invalidate.iteritems(): self._invalidateItems(itemTypeID, uniqueIDs) return invalidate def getVehicle(self, vehInvID): vehInvData = self.__inventory.getVehicleData(vehInvID) return self.__makeVehicle(vehInvData.descriptor.type.compactDescr, vehInvData) if vehInvData is not None else None def getStockVehicle(self, typeCompDescr, useInventory=False): if getTypeOfCompactDescr(typeCompDescr) == GUI_ITEM_TYPE.VEHICLE: proxy = self if useInventory else None return self.itemsFactory.createVehicle(typeCompDescr=typeCompDescr, proxy=proxy) else: return def getVehicleCopy(self, vehicle): return self.itemsFactory.createVehicle(typeCompDescr=vehicle.intCD, strCompactDescr=vehicle.descriptor.makeCompactDescr(), inventoryID=vehicle.invID, proxy=self) def getTankman(self, tmanInvID): tankman = None tmanInvData = self.__inventory.getTankmanData(tmanInvID) if tmanInvData is not None: tankman = self.__makeTankman(tmanInvID, tmanInvData) else: duration = self.__shop.tankmenRestoreConfig.billableDuration tankmanData = self.__recycleBin.getTankman(tmanInvID, duration) if tankmanData is not None: tankman = self.__makeDismissedTankman(tmanInvID, tankmanData) return tankman def getItems(self, itemTypeID=None, criteria=REQ_CRITERIA.EMPTY, nationID=None): result = ItemsCollection() if not isinstance(itemTypeID, tuple): itemTypeID = (itemTypeID,) for typeID in itemTypeID: if typeID == GUI_ITEM_TYPE.VEHICLE and nationID is None and criteria.lookInInventory(): vehGetter = self.getVehicle for vehInvID in (self.inventory.getItems(GUI_ITEM_TYPE.VEHICLE) or {}).iterkeys(): item = vehGetter(vehInvID) if criteria(item): result[item.intCD] = item itemGetter = self.getItemByCD protector = criteria.getIntCDProtector() if protector is not None and protector.isUnlinked(): return result for intCD in vehicle_items_getter.getItemsIterator(self.__shop.getItemsData(), nationID=nationID, itemTypeID=typeID): if protector is not None and protector.isTriggered(intCD): continue item = itemGetter(intCD) if criteria(item): result[intCD] = item return result def getTankmen(self, criteria=REQ_CRITERIA.TANKMAN.ACTIVE): result = ItemsCollection() activeTankmenInvData = self.__inventory.getItemsData(GUI_ITEM_TYPE.TANKMAN) for invID, tankmanInvData in activeTankmenInvData.iteritems(): item = self.__makeTankman(invID, tankmanInvData) if criteria(item): result[invID] = item duration = self.__shop.tankmenRestoreConfig.billableDuration dismissedTankmenData = self.__recycleBin.getTankmen(duration) for invID, tankmanData in dismissedTankmenData.iteritems(): item = self.__makeDismissedTankman(invID, tankmanData) if criteria(item): result[invID] = item return result def getVehicles(self, criteria=REQ_CRITERIA.EMPTY): return self.getItems(GUI_ITEM_TYPE.VEHICLE, criteria=criteria) def getBadges(self, criteria=REQ_CRITERIA.EMPTY): result = ItemsCollection() for badgeID, badgeData in self.__badges.available.iteritems(): item = self.itemsFactory.createBadge(badgeData, proxy=self) if criteria(item): result[badgeID] = item return result def getItemByCD(self, typeCompDescr): return self.__makeVehicle(typeCompDescr) if getTypeOfCompactDescr(typeCompDescr) == GUI_ITEM_TYPE.VEHICLE else self.__makeSimpleItem(typeCompDescr) def getItem(self, itemTypeID, nationID, innationID): typeCompDescr = vehicles.makeIntCompactDescrByID(GUI_ITEM_TYPE_NAMES[itemTypeID], nationID, innationID) return self.__makeVehicle(typeCompDescr) if itemTypeID == GUI_ITEM_TYPE.VEHICLE else self.__makeSimpleItem(typeCompDescr) def getTankmanDossier(self, tmanInvID): tankman = self.getTankman(tmanInvID) tmanDossierDescr = self.__getTankmanDossierDescr(tmanInvID) currentVehicleItem = None if tankman.isInTank: extDossier = self.getVehicleDossier(tankman.vehicleDescr.type.compactDescr) currentVehicleItem = self.getItemByCD(tankman.vehicleDescr.type.compactDescr) else: extDossier = self.getAccountDossier() return self.itemsFactory.createTankmanDossier(tankman.descriptor, tmanDossierDescr, extDossier, currentVehicleItem=currentVehicleItem) def getVehicleDossier(self, vehTypeCompDescr, databaseID=None): if databaseID is None: return self.itemsFactory.createVehicleDossier(self.__getVehicleDossierDescr(vehTypeCompDescr), vehTypeCompDescr) else: container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER] dossier = container.get((int(databaseID), vehTypeCompDescr)) if dossier is None: LOG_WARNING('Vehicle dossier for this user is empty', vehTypeCompDescr, databaseID) return playerDossier = self.getAccountDossier(databaseID) return self.itemsFactory.createVehicleDossier(dossier, vehTypeCompDescr, playerDBID=databaseID, rankedCurrentSeason=playerDossier.getRankedCurrentSeason()) def getVehicleDossiersIterator(self): for intCD, dossier in self.__dossiers.getVehDossiersIterator(): yield (intCD, dossiers2.getVehicleDossierDescr(dossier)) def getAccountDossier(self, databaseID=None): if databaseID is None: dossierDescr = self.__getAccountDossierDescr() return self.itemsFactory.createAccountDossier(dossierDescr) container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER] dossier, _, _, ranked = container.get(int(databaseID)) if dossier is None: LOG_WARNING('Trying to get empty user dossier', databaseID) return else: return self.itemsFactory.createAccountDossier(dossier, databaseID, rankedCurrentSeason=ranked) def getClanInfo(self, databaseID=None): if databaseID is None: return (self.__stats.clanDBID, self.__stats.clanInfo) container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER] _, clanInfo, _, _ = container.get(int(databaseID)) if clanInfo is None: LOG_WARNING('Trying to get empty user clan info', databaseID) return else: return clanInfo def getPreviousItem(self, itemTypeID, invDataIdx): itemData = self.__inventory.getPreviousItem(itemTypeID, invDataIdx) return self.__makeItem(itemTypeID, invDataIdx, strCompactDescr=itemData.compDescr, inventoryID=itemData.invID, proxy=self) def doesVehicleExist(self, intCD): itemTypeID, nationID, innationID = vehicles.parseIntCompactDescr(intCD) return innationID in vehicles.g_list.getList(nationID) def _invalidateItems(self, itemTypeID, uniqueIDs): cache = self.__itemsCache[itemTypeID] for uid in uniqueIDs: invRes = self.__inventory.invalidateItem(itemTypeID, uid) if uid in cache: LOG_DEBUG('Item marked as invalid', uid, cache[uid], invRes) self.__deleteItemFromCache(cache, uid, itemTypeID) LOG_DEBUG('No cached item', uid, invRes) def _invalidateUnlocks(self, unlocked, result): vehInCache = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE] for itemCD in unlocked: itemTypeID = getTypeOfCompactDescr(itemCD) if itemTypeID == GUI_ITEM_TYPE.VEHICLE: result[itemTypeID].add(itemCD) if itemCD in vehInCache: self._invalidateUnlocks(vehInCache[itemCD].getAutoUnlockedItems(), result) if itemTypeID in GUI_ITEM_TYPE.VEHICLE_MODULES: result[itemTypeID].add(itemCD) if itemTypeID != GUI_ITEM_TYPE.FUEL_TANK: LOG_WARNING('Item is not vehicle or module', itemTypeID) def __deleteItemFromCache(self, cache, uid, itemTypeID): if itemTypeID == GUI_ITEM_TYPE.VEHICLE: item = cache[uid] if item.isCustomStateSet(): self.__vehCustomStateCache[uid] = item.getCustomState() elif uid in self.__vehCustomStateCache: del self.__vehCustomStateCache[uid] del cache[uid] def __getAccountDossierDescr(self): return dossiers2.getAccountDossierDescr(self.__stats.accountDossier) def __getTankmanDossierDescr(self, tmanInvID): tmanData = self.__inventory.getTankmanData(tmanInvID) return dossiers2.getTankmanDossierDescr(tmanData.descriptor.dossierCompactDescr) if tmanData is not None else dossiers2.getTankmanDossierDescr() def __getVehicleDossierDescr(self, vehTypeCompDescr): return dossiers2.getVehicleDossierDescr(self.__dossiers.getVehicleDossier(vehTypeCompDescr)) def __makeItem(self, itemTypeIdx, uid, *args, **kwargs): container = self.__itemsCache[itemTypeIdx] if uid in container: return container[uid] else: if not self.isSynced(): self.__logBrokenSync() item = self.itemsFactory.createGuiItem(itemTypeIdx, *args, **kwargs) if item is not None: container[uid] = item self.__restoreItemCustomState(itemTypeIdx, uid, item) return item def __restoreItemCustomState(self, itemTypeIdx, uid, item): if itemTypeIdx == GUI_ITEM_TYPE.VEHICLE: prevItem = self.__vehCustomStateCache.get(uid, None) if prevItem: item.setCustomState(prevItem) del self.__vehCustomStateCache[uid] return def __makeVehicle(self, typeCompDescr, vehInvData=None): vehInvData = vehInvData or self.__inventory.getItemData(typeCompDescr) return self.__makeItem(GUI_ITEM_TYPE.VEHICLE, typeCompDescr, strCompactDescr=vehInvData.compDescr, inventoryID=vehInvData.invID, proxy=self) if vehInvData is not None else self.__makeItem(GUI_ITEM_TYPE.VEHICLE, typeCompDescr, typeCompDescr=typeCompDescr, proxy=self) def __makeTankman(self, tmanInvID, tmanInvData=None): tmanInvData = tmanInvData or self.__inventory.getTankmanData(tmanInvID) if tmanInvData is not None: vehicle = None if tmanInvData.vehicle > 0: vehicle = self.getVehicle(tmanInvData.vehicle) return self.__makeItem(GUI_ITEM_TYPE.TANKMAN, tmanInvID, strCompactDescr=tmanInvData.compDescr, inventoryID=tmanInvID, vehicle=vehicle, proxy=self) else: return def __makeDismissedTankman(self, tmanID, tmanData): strCD, dismissedAt = tmanData return self.__makeItem(GUI_ITEM_TYPE.TANKMAN, tmanID, strCompactDescr=strCD, inventoryID=tmanID, proxy=self, dismissedAt=dismissedAt) def __makeSimpleItem(self, typeCompDescr): return self.__makeItem(getTypeOfCompactDescr(typeCompDescr), typeCompDescr, intCompactDescr=typeCompDescr, proxy=self) def __getTankmenIDsForVehicle(self, vehData): vehTmanIDs = set() for tmanInvID in vehData.crew: if tmanInvID is not None: vehTmanIDs.add(tmanInvID) return vehTmanIDs def __getTankmenIDsForTankman(self, tmanData): vehData = self.__inventory.getVehicleData(tmanData.vehicle) return self.__getTankmenIDsForVehicle(vehData) if vehData is not None else set() def __getVehicleCDForTankman(self, tmanData): vehData = self.__inventory.getVehicleData(tmanData.vehicle) return {vehData.descriptor.type.compactDescr} if vehData is not None else set() def __logBrokenSync(self): requesters = (self.__stats, self.__inventory, self.__recycleBin, self.__shop, self.__dossiers, self.__goodies, self.__vehicleRotation, self.ranked) unsyncedList = [ r.__class__.__name__ for r in [ r for r in requesters if not r.isSynced() ] ] LOG_ERROR('Trying to create fitting item when requesters are not fully synced:', unsyncedList, stack=True) def __updateStyleAppliedCount(self, styleId, vehicleIntCD, count): if styleId == 0: return None else: styleIntCD = vehicles.makeIntCompactDescrByID('customizationItem', CustomizationType.STYLE, styleId) self.__inventory.updateC11nItemAppliedCount(styleIntCD, vehicleIntCD, count) return styleIntCD