class BerserkerSoundPlayer(_VehicleStateSoundPlayer): def __init__(self): self.__effectIsWorking = False self.__endTime = 0 self.__delayer = None return def _onVehicleStateUpdated(self, state, value): if state == VEHICLE_VIEW_STATE.DOT_EFFECT: if value is not None: if value.attackReasonID == ATTACK_REASONS.index( ATTACK_REASON.BERSERKER): self.__effectIsWorking = True self.__endTime = value.endTime BREvents.playSound(BREvents.BERSERKER_ACTIVATION) self.__delayer = CallbackDelayer() self.__delayer.delayCallback(value.period, self.__updateShowDotEffect, value.period) elif self.__effectIsWorking and BigWorld.serverTime( ) >= self.__endTime: self.__effectIsWorking = False self.__endTime = 0 BREvents.playSound(BREvents.BERSERKER_DEACTIVATION) self.__delayer.stopCallback(self.__updateShowDotEffect) self.__delayer = None return def __updateShowDotEffect(self, period): BREvents.playSound(BREvents.BERSERKER_PULSE_RED) return period
class _ArtyHitMarkerController(_SPGGunMarkerController): def __init__(self, gunMakerType, dataProvider, artyEquipmentUDO, areaRadius, interval=0.1): super(_ArtyHitMarkerController, self).__init__(gunMakerType, dataProvider, enabledFlag=_MARKER_FLAG.ARTY_HIT_ENABLED) self.__artyEquipmentUDO = artyEquipmentUDO self.__areaRadius = areaRadius self.__interval = interval self.__delayer = CallbackDelayer() self.__trajectoryDrawer = BigWorld.wg_trajectory_drawer() def create(self): super(_ArtyHitMarkerController, self).create() self.__trajectoryDrawer.setColors(Math.Vector4(0, 255, 0, 255), Math.Vector4(255, 0, 0, 255), Math.Vector4(128, 128, 128, 255)) self.__trajectoryDrawer.setIgnoredIDs([BigWorld.player().playerVehicleID]) def destroy(self): self.__artyEquipmentUDO = None if self.__trajectoryDrawer is not None: self.__trajectoryDrawer.visible = False self.__trajectoryDrawer = None if self.__delayer is not None: self.__delayer.destroy() self.__delayer = None super(_ArtyHitMarkerController, self).destroy() return def enable(self): super(_ArtyHitMarkerController, self).enable() self.__delayer.delayCallback(self.__interval, self.__tick) self.__trajectoryDrawer.setParams(1000.0, Math.Vector3(0, -self.__artyEquipmentUDO.gravity, 0), (0, 0)) def disable(self): self.__delayer.stopCallback(self.__tick) super(_ArtyHitMarkerController, self).disable() def setVisible(self, flag): self.__trajectoryDrawer.visible = flag def getPointsInside(self, positions): return self._dataProvider.getPointsInside(positions) def _getCurrentShotInfo(self): launchPosition = self._position + self.__artyEquipmentUDO.position launchVelocity = self.__artyEquipmentUDO.launchVelocity gravity = Math.Vector3(0, -self.__artyEquipmentUDO.gravity, 0) return (launchPosition, launchVelocity, gravity) def _updateDispersionData(self): self._dataProvider.setupFlatRadialDispersion(self.__areaRadius) def __tick(self): self.__trajectoryDrawer.update(self._position, self._position + self.__artyEquipmentUDO.position, self.__artyEquipmentUDO.launchVelocity, self.__interval) return self.__interval
class CombatEquipmentManager(object): guiSessionProvider = dependency.descriptor(IBattleSessionProvider) def testArtyStrike(self, strikeID=33, offset=Vector3(0, 0, 0)): if not IS_DEVELOPMENT: return else: p = Vector3(BigWorld.camera().position) d = BigWorld.camera().direction collRes = BigWorld.wg_collideSegment(BigWorld.player().spaceID, p, p + d * 1000, 18, 8) if collRes is None: return strikePos = collRes.closestPoint vDir = Vector2(d.x, d.z) vDir.normalise() self.setEquipmentApplicationPoint(strikeID, strikePos + offset, vDir) return def __init__(self): self.__callbackDelayer = CallbackDelayer() self.__selectedAreas = {} self.__wings = {} self.__isGUIVisible = True if _ENABLE_DEBUG_DRAW: self.debugPolyLine = Flock.DebugPolyLine() self.debugPoints = [] self.debugDirs = [] self.__lastSmokeInfos = None self.__onCombatEquipmentShotCB = None return def onBecomePlayer(self): pass def handleKey(self, isDown, key, mods): return False def onBecomeNonPlayer(self): for area in self.__selectedAreas.itervalues(): area.destroy() for wing in self.__wings.itervalues(): wing.destroy() self.__callbackDelayer.destroy() self.__selectedAreas = {} self.__wings = {} SmokeScreen.enableSmokePostEffect(False) def updatePlaneTrajectory(self, equipmentID, team, curTime, curPos, curDir, nextTime, nextPos, nextDir, isEndOfFlight): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== updatePlaneTrajectory =====') LOG_DEBUG(equipmentID, team) LOG_DEBUG(curPos, curDir, curTime) LOG_DEBUG(nextPos, nextDir, nextTime) LOG_DEBUG(isEndOfFlight) moveDir = nextPos - curPos moveDir.normalise() nextDir3d = Vector3(nextDir.x, moveDir.y, nextDir.y) nextDir3d.normalise() startP = BombersWing.CurveControlPoint(curPos, Vector3(curDir.x, 0, curDir.y), curTime) nextP = BombersWing.CurveControlPoint(nextPos, nextDir3d, nextTime) points = (startP, nextP) wingID = (team, equipmentID) wing = self.__wings.get(wingID) if wing is None or wing.withdrawn: if wing is not None: wing.destroy() wing = BombersWing.BombersWing(equipmentID, points) self.__wings[wingID] = wing if isEndOfFlight: wing.addControlPoint(points, isEndOfFlight) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(curPos) self.debugDirs.append(curDir) else: wing.addControlPoint(points, isEndOfFlight) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(nextPos) self.debugDirs.append(nextDir) self.debugPoints.append(nextPos + Vector3(nextDir.x, 0, nextDir.y) * 10) self.debugPoints.append(nextPos) self.debugPolyLine.set(self.debugPoints) return def showHittingArea(self, equipmentID, pos, direction, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== showHittingArea =====') LOG_DEBUG(equipmentID) LOG_DEBUG(pos, direction, time) correctedCoords = tuple((int(x * 1000.0) for x in pos.tuple())) areaUID = (int(equipmentID), correctedCoords) if areaUID in self.__selectedAreas: return eq = vehicles.g_cache.equipments()[equipmentID] if BattleReplay.isPlaying(): BigWorld.callback(0.0, functools.partial(self.__showMarkerCallback, eq, pos, direction, time, areaUID)) else: self.__showMarkerCallback(eq, pos, direction, time, areaUID) def onCombatEquipmentShotLaunched(self, equipmentID, position): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== onCombatEquipmentShotLaunched =====') LOG_DEBUG(equipmentID, position) equipment = vehicles.g_cache.equipments().get(equipmentID) if equipment is None: return elif equipment.wwsoundShot is None: LOG_DEBUG('LOG_GOGGI - wwsoundShot is None for ', equipment.name) return else: shotSoundPreDelay = 0.0 if hasattr(equipment, 'shotSoundPreDelay'): if equipment.shotSoundPreDelay is not None: shotSoundPreDelay = equipment.shotSoundPreDelay delay = 0.0 if hasattr(equipment, 'delay'): delay = equipment.delay elif hasattr(equipment, 'minDelay'): delay = equipment.minDelay if delay > shotSoundPreDelay: delay = delay - shotSoundPreDelay self.__onCombatEquipmentShotCB = BigWorld.callback(delay, functools.partial(self.__triggerOnCombatEquipmentShot, equipment.wwsoundShot, position)) LOG_DEBUG('LOG_GOGGI - actual shot delay: ', delay, ' equipment.wwsoundShot: ', equipment.wwsoundShot) return def __triggerOnCombatEquipmentShot(self, eventName, position): SoundGroups.g_instance.playSoundPos(eventName, position) def __delayedAreaDestroy(self, areaUID): area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() return def __showMarkerCallback(self, eq, pos, direction, time, areaUID): timer = round(time - BigWorld.serverTime()) if timer <= 0.0: return else: area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() self.__selectedAreas[areaUID] = self.createEquipmentSelectedArea(pos, direction, eq) area = self.__selectedAreas[areaUID] if area is not None: area.setGUIVisible(self.__isGUIVisible) self.__callbackDelayer.delayCallback(timer, functools.partial(self.__delayedAreaDestroy, areaUID)) ctrl = self.guiSessionProvider.shared.equipments if ctrl is not None: ctrl.showMarker(eq, pos, direction, timer) return def setGUIVisible(self, isVisible): self.__isGUIVisible = isVisible for area in self.__selectedAreas.itervalues(): area.setGUIVisible(self.__isGUIVisible) @staticmethod def __calcBombsDistribution(bombsCnt, areaWidth, areaLength): coeff = areaWidth / areaLength bombsPerWidth = math.sqrt(bombsCnt * coeff) bombsPerLength = bombsPerWidth / coeff return (bombsPerWidth, bombsPerLength) def showCarpetBombing(self, equipmentID, pos, direction, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== showCarpetBombing =====') LOG_DEBUG(equipmentID) LOG_DEBUG(pos, direction, time) bombEquipment = vehicles.g_cache.equipments()[equipmentID] shellDescr = vehicles.getItemByCompactDescr(bombEquipment.shellCompactDescr) shotEffect = vehicles.g_cache.shotEffects[shellDescr.effectsIndex] airstrikeID = shotEffect.get('airstrikeID') if airstrikeID is None: LOG_ERROR('EquipmentID %s has no airstrike shot effect settings' % equipmentID) return else: areaWidth, areaLength = bombEquipment.areaWidth, bombEquipment.areaLength if _ENABLE_DEBUG_LOG: LOG_DEBUG('Ideal', areaWidth, areaLength) beginExplosionPos = BigWorld.wg_collideSegment(BigWorld.player().spaceID, pos, pos + direction * 1000.0, 18) if beginExplosionPos is None: return beginExplosionPos = beginExplosionPos.closestPoint flatDir = Vector3(direction) flatDir.y = 0.0 flatDir.normalise() endDropPoint = pos + flatDir * (areaLength * bombEquipment.waveFraction) endExplosionPos = BigWorld.wg_collideSegment(BigWorld.player().spaceID, endDropPoint, endDropPoint + direction * 1000.0, 18) if endExplosionPos is None: endExplosionPos = beginExplosionPos + flatDir * (areaLength * bombEquipment.waveFraction) else: endExplosionPos = endExplosionPos.closestPoint areaLength = beginExplosionPos.flatDistTo(endExplosionPos) averageBombCount = bombEquipment.bombsNumber bombsPerWidth, bombsPerLength = CombatEquipmentManager.__calcBombsDistribution(averageBombCount, areaWidth, areaLength) delay = time - BigWorld.serverTime() explosionVelocity = flatDir * bombEquipment.speed partialAirstrikeFunc = functools.partial(BigWorld.PyGroundEffectManager().playAirstrike, airstrikeID, beginExplosionPos, explosionVelocity, areaWidth, areaLength, math.ceil(bombsPerWidth), math.ceil(bombsPerLength)) if _ENABLE_DEBUG_LOG: LOG_DEBUG('delta', delay) LOG_DEBUG('pos, dir', pos, direction) LOG_DEBUG('Params for artyStrike effect', airstrikeID, beginExplosionPos, flatDir, areaWidth, areaLength, bombsPerWidth, bombsPerLength) if delay < 0.0: partialAirstrikeFunc() else: self.__callbackDelayer.delayCallback(delay, partialAirstrikeFunc) if _ENABLE_DEBUG_DRAW: self.debugStartLine = Flock.DebugLine(pos, beginExplosionPos) self.debugEndLine = Flock.DebugLine(endDropPoint, endExplosionPos) self.__callbackDelayer.delayCallback(delay, functools.partial(_DebugFrontLine.launch, beginExplosionPos, endExplosionPos, areaWidth, explosionVelocity)) return def setEquipmentApplicationPoint(self, equipmentID, point, direction): myTeam = BigWorld.player().team wingID = (myTeam, equipmentID) wing = self.__wings.get(wingID) if wing is not None: wing.destroy() del self.__wings[wingID] self.cell.setEquipmentApplicationPoint(equipmentID, point, direction) return @staticmethod def createEquipmentSelectedArea(pos, direction, equipment): area = CombatSelectedArea.CombatSelectedArea() size = Vector2(equipment.areaWidth, equipment.areaLength) visual = equipment.areaVisual color = equipment.areaColor marker = equipment.areaMarker if visual is None: visual = CombatSelectedArea.DEFAULT_RADIUS_MODEL if color is None: pass if marker is None: pass area.setup(pos, direction, size, visual, color, marker) return area def onSmoke(self, smokeInfos): ctrl = self.guiSessionProvider.shared.vehicleState self.__lastSmokeInfos = smokeInfos if ctrl is not None: ctrl.notifyStateChanged(VEHICLE_VIEW_STATE.SMOKE, smokeInfos) SmokeScreen.enableSmokePostEffect(bool(smokeInfos), smokeInfos) SmokeScreen.enableSmokePostEffect(bool(smokeInfos), smokeInfos) return @property def lastSmokeInfos(self): return self.__lastSmokeInfos
class DetachedTurret(BigWorld.Entity, ComponentSystem): allTurrets = list() def __init__(self): ComponentSystem.__init__(self) self.__vehDescr = vehicles.VehicleDescr( compactDescr=self.vehicleCompDescr) self.filter = BigWorld.WGTurretFilter() self.__detachConfirmationTimer = SynchronousDetachment(self) self.__detachConfirmationTimer.onInit() self.__detachmentEffects = None self.targetFullBounds = True self.targetCaps = [1] self.__isBeingPulledCallback = None self.__hitEffects = None self.__vehicleStickers = None return def reload(self): pass def __prepareModelAssembler(self): assembler = BigWorld.CompoundAssembler(self.__vehDescr.name, self.spaceID) turretModel = self.__vehDescr.turret.models.exploded gunModel = self.__vehDescr.gun.models.exploded assembler.addRootPart(turretModel, TankPartNames.TURRET) assembler.emplacePart(gunModel, TankNodeNames.GUN_JOINT, TankPartNames.GUN) return assembler def prerequisites(self): prereqs = [self.__prepareModelAssembler()] prereqs += self.__vehDescr.prerequisites() return prereqs def onEnterWorld(self, prereqs): self.model = prereqs[self.__vehDescr.name] self.model.matrix = self.matrix self.__detachConfirmationTimer.onEnterWorld() self.__vehDescr.keepPrereqs(prereqs) turretDescr = self.__vehDescr.turret if self.isUnderWater == 0: self.__detachmentEffects = _TurretDetachmentEffects( self.model, turretDescr.turretDetachmentEffects, self.isCollidingWithWorld == 1) self.addComponent(self.__detachmentEffects) else: self.__detachmentEffects = None self.__hitEffects = _HitEffects(self.model) self.addComponent(self.__hitEffects) self.__componentsDesc = (self.__vehDescr.turret, self.__vehDescr.gun) for desc in self.__componentsDesc: desc.hitTester.loadBspModel() from helpers.CallbackDelayer import CallbackDelayer self.__isBeingPulledCallback = CallbackDelayer() self.__isBeingPulledCallback.delayCallback(self.__checkIsBeingPulled(), self.__checkIsBeingPulled) DetachedTurret.allTurrets.append(self) ProjectileAwareEntities.addEntity(self) BigWorld.callback(0.0, self.__createAndAttachStickers) return def __createAndAttachStickers(self): if self.__vehicleStickers is not None: return else: from VehicleStickers import VehicleStickers vehicle = BigWorld.entity(self.vehicleID) if vehicle is not None: self.__vehicleStickers = VehicleStickers( self.__vehDescr, vehicle.publicInfo['marksOnGun']) self.__vehicleStickers.alpha = vehicles.g_cache.commonConfig[ 'miscParams']['damageStickerAlpha'] self.__vehicleStickers.attach(self.model, True, False, True) return def onLeaveWorld(self): ComponentSystem.destroy(self) DetachedTurret.allTurrets.remove(self) ProjectileAwareEntities.removeEntity(self) self.__detachConfirmationTimer.cancel() self.__detachConfirmationTimer = None self.__isBeingPulledCallback.destroy() self.__isBeingPulledCallback = None if self.__vehicleStickers is not None: self.__vehicleStickers.detach() self.__vehicleStickers = None return def onStaticCollision(self, energy, point, normal): if self.__detachmentEffects is not None: surfaceMaterial = calcSurfaceMaterialNearPoint( point, normal, self.spaceID) effectIdx = surfaceMaterial.effectIdx groundEffect = True distToWater = BigWorld.wg_collideWater(self.position, surfaceMaterial.point) if distToWater != -1: vel = Math.Vector3(self.velocity).length if vel < _MIN_COLLISION_SPEED: groundEffect = False effectIdx = material_kinds.EFFECT_MATERIAL_INDEXES_BY_NAMES[ 'water'] self.__detachmentEffects.notifyAboutCollision( energy, point, effectIdx, groundEffect, self.isUnderWater) return def showDamageFromShot(self, points, effectsIndex): maxHitEffectCode, decodedPoints, _ = DamageFromShotDecoder.decodeHitPoints( points, self.__vehDescr) for shotPoint in decodedPoints: if shotPoint.componentName == TankPartNames.TURRET or shotPoint.componentName == TankPartNames.GUN: self.__hitEffects.showHit(shotPoint, effectsIndex, shotPoint.componentName) else: LOG_ERROR( "Detached turret got hit into %s component, but it's impossible" % shotPoint.componentName) def collideSegment(self, startPoint, endPoint, skipGun=False): res = None filterMethod = getattr(self.filter, 'segmentMayHitEntity', lambda: True) if not filterMethod(startPoint, endPoint, 0): return res else: matricesToCheck = [Matrix(self.model.matrix)] if not skipGun: matricesToCheck.append( Matrix(self.model.node(TankPartNames.GUN))) for matrix, desc in zip(matricesToCheck, self.__componentsDesc): toModel = matrix toModel.invert() collisions = desc.hitTester.localHitTest( toModel.applyPoint(startPoint), toModel.applyPoint(endPoint)) if collisions is None: continue for dist, _, hitAngleCos, matKind in collisions: if res is None or res.dist >= dist: matInfo = desc.materials.get(matKind) res = SegmentCollisionResult( dist, hitAngleCos, matInfo.armor if matInfo is not None else 0) return res def set_isUnderWater(self, prev): if self.__detachmentEffects is not None: if self.isUnderWater: self.__detachmentEffects.stopEffects() return def set_isCollidingWithWorld(self, prev): pass def changeAppearanceVisibility(self, isVisible): self.model.visible = isVisible self.__createAndAttachStickers() def __checkIsBeingPulled(self): if self.__detachmentEffects is not None: if self.isCollidingWithWorld and not self.isUnderWater and self.velocity.lengthSquared > 0.1: extent = Math.Matrix( self.model.getBoundsForRoot()).applyVector( Math.Vector3(0.5, 0.5, 0.5)).length surfaceMaterial = calcSurfaceMaterialNearPoint( self.position, Math.Vector3(0, extent, 0), self.spaceID) self.__detachmentEffects.notifyAboutBeingPulled( True, surfaceMaterial.effectIdx) if surfaceMaterial.matKind == 0: LOG_ERROR( 'calcSurfaceMaterialNearPoint failed to find the collision point at: ', self.position) else: self.__detachmentEffects.notifyAboutBeingPulled(False, None) return SERVER_TICK_LENGTH
class Hangar(LobbySelectableView, HangarMeta, IGlobalListener): _SOUND_STATE_PLACE = 'STATE_hangar_place' _SOUND_STATE_PLACE_GARAGE = 'STATE_hangar_place_garage' __background_alpha__ = 0.0 __SOUND_SETTINGS = CommonSoundSpaceSettings( name='hangar', entranceStates={ _SOUND_STATE_PLACE: _SOUND_STATE_PLACE_GARAGE, StatesGroup.HANGAR_FILTERED: States.HANGAR_FILTERED_OFF }, exitStates={}, persistentSounds=(), stoppableSounds=(), priorities=(), autoStart=True, enterEvent='', exitEvent='') rankedController = dependency.descriptor(IRankedBattlesController) epicController = dependency.descriptor(IEpicBattleMetaGameController) battlePassController = dependency.descriptor(IBattlePassController) battleRoyaleController = dependency.descriptor(IBattleRoyaleController) bootcampController = dependency.descriptor(IBootcampController) itemsCache = dependency.descriptor(IItemsCache) igrCtrl = dependency.descriptor(IIGRController) lobbyContext = dependency.descriptor(ILobbyContext) statsCollector = dependency.descriptor(IStatisticsCollector) gui = dependency.descriptor(IGuiLoader) _settingsCore = dependency.descriptor(ISettingsCore) hangarSpace = dependency.descriptor(IHangarSpace) _promoController = dependency.descriptor(IPromoController) _connectionMgr = dependency.descriptor(IConnectionManager) _offersBannerController = dependency.descriptor(IOffersBannerController) __mapboxCtrl = dependency.descriptor(IMapboxController) __marathonCtrl = dependency.descriptor(IMarathonEventsController) __funRandomController = dependency.descriptor(IFunRandomController) _COMMON_SOUND_SPACE = __SOUND_SETTINGS def __init__(self, _=None): LobbySelectableView.__init__(self, 0) self.__currentCarouselAlias = None self.__isSpaceReadyForC11n = False self.__isVehicleReadyForC11n = False self.__isVehicleCameraReadyForC11n = False self.__isUnitJoiningInProgress = False self.__urlMacros = URLMacros() self.__teaser = None self.__timer = None self.__wotPlusInfo = BigWorld.player().renewableSubscription self.__updateDogTagsState() self.__updateWotPlusState() return def onEscape(self): dialogsContainer = self.app.containerManager.getContainer( WindowLayer.TOP_WINDOW) if not dialogsContainer.getView( criteria={POP_UP_CRITERIA.VIEW_ALIAS: VIEW_ALIAS.LOBBY_MENU}): self.fireEvent(events.LoadViewEvent( SFViewLoadParams(VIEW_ALIAS.LOBBY_MENU)), scope=EVENT_BUS_SCOPE.LOBBY) def onCloseBtnClick(self): self.battleRoyaleController.selectRandomBattle() def hideTeaser(self): self.__teaser.stop(byUser=True) self.__teaser = None return def onTeaserClick(self): self._promoController.showLastTeaserPromo() def showHelpLayout(self): windows = self.gui.windowsManager.findWindows( predicateHelpLayoutAllowedWindow) if not windows: self.gui.windowsManager.onWindowStatusChanged += self.__onWindowLoaded self.fireEvent(LobbySimpleEvent(LobbySimpleEvent.SHOW_HELPLAYOUT), scope=EVENT_BUS_SCOPE.LOBBY) self.as_showHelpLayoutS() def closeHelpLayout(self): self.gui.windowsManager.onWindowStatusChanged -= self.__onWindowLoaded nextTick( partial(self.fireEvent, LobbySimpleEvent(LobbySimpleEvent.CLOSE_HELPLAYOUT), EVENT_BUS_SCOPE.LOBBY)) self.as_closeHelpLayoutS() def _populate(self): LobbySelectableView._populate(self) self.__isSpaceReadyForC11n = self.hangarSpace.spaceInited self.__isVehicleReadyForC11n = self.hangarSpace.isModelLoaded self.__checkVehicleCameraState() g_currentVehicle.onChanged += self.__onCurrentVehicleChanged self.hangarSpace.onVehicleChangeStarted += self.__onVehicleLoading self.hangarSpace.onVehicleChanged += self.__onVehicleLoaded self.hangarSpace.onSpaceRefresh += self.__onSpaceRefresh self.hangarSpace.onSpaceCreate += self.__onSpaceCreate self.igrCtrl.onIgrTypeChanged += self.__onIgrTypeChanged self.itemsCache.onSyncCompleted += self.onCacheResync self.rankedController.onUpdated += self.onRankedUpdate self.rankedController.onGameModeStatusTick += self.__updateAlertMessage self.__mapboxCtrl.onPrimeTimeStatusUpdated += self.__updateAlertMessage self.__funRandomController.onGameModeStatusUpdated += self.__updateAlertMessage self.battleRoyaleController.onUpdated += self.__updateBattleRoyaleComponents self.epicController.onUpdated += self.__onEpicBattleUpdated self.epicController.onPrimeTimeStatusUpdated += self.__onEpicBattleUpdated self.epicController.onGameModeStatusTick += self.__updateAlertMessage self._promoController.onNewTeaserReceived += self.__onTeaserReceived self.hangarSpace.setVehicleSelectable(True) g_prbCtrlEvents.onVehicleClientStateChanged += self.__onVehicleClientStateChanged g_playerEvents.onPrebattleInvitationAccepted += self.__onPrebattleInvitationAccepted unitMgr = prb_getters.getClientUnitMgr() if unitMgr: unitMgr.onUnitJoined += self.__onUnitJoined g_clientUpdateManager.addCallbacks( {'inventory': self.__updateAlertMessage}) self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingChanged self._settingsCore.onSettingsChanged += self.__onSettingsChanged self.__wotPlusInfo.onRenewableSubscriptionDataChanged += self.__onWotPlusDataChanged self.battlePassController.onSeasonStateChanged += self.__switchCarousels self.startGlobalListening() self.__updateAll() self.addListener(LobbySimpleEvent.WAITING_SHOWN, self.__onWaitingShown, EVENT_BUS_SCOPE.LOBBY) self.addListener(events.FightButtonEvent.FIGHT_BUTTON_UPDATE, self.__handleFightButtonUpdated, scope=EVENT_BUS_SCOPE.LOBBY) self.addListener(CameraRelatedEvents.CAMERA_ENTITY_UPDATED, self.__handleSelectedEntityUpdated) self.statsCollector.noteHangarLoadingState( HANGAR_LOADING_STATE.HANGAR_UI_READY, showSummaryNow=True) lobbyContext = dependency.instance(ILobbyContext) isCrewBooksEnabled = lobbyContext.getServerSettings( ).isCrewBooksEnabled() getTutorialGlobalStorage().setValue(GLOBAL_FLAG.CREW_BOOKS_ENABLED, isCrewBooksEnabled) self.__timer = CallbackDelayer() self.as_setNotificationEnabledS( crewBooksViewedCache().haveNewCrewBooks()) self._offersBannerController.showBanners() self.fireEvent(events.HangarCustomizationEvent( events.HangarCustomizationEvent.RESET_VEHICLE_MODEL_TRANSFORM), scope=EVENT_BUS_SCOPE.LOBBY) if g_currentVehicle.isPresent(): g_currentVehicle.refreshModel() if self.bootcampController.isInBootcamp(): self.as_setDQWidgetLayoutS( DAILY_QUESTS_WIDGET_CONSTANTS.WIDGET_LAYOUT_SINGLE) def _dispose(self): self.removeListener(LobbySimpleEvent.WAITING_SHOWN, self.__onWaitingShown, EVENT_BUS_SCOPE.LOBBY) self.removeListener(events.FightButtonEvent.FIGHT_BUTTON_UPDATE, self.__handleFightButtonUpdated, scope=EVENT_BUS_SCOPE.LOBBY) self.removeListener(CameraRelatedEvents.CAMERA_ENTITY_UPDATED, self.__handleSelectedEntityUpdated) self.itemsCache.onSyncCompleted -= self.onCacheResync g_currentVehicle.onChanged -= self.__onCurrentVehicleChanged self.hangarSpace.onVehicleChangeStarted -= self.__onVehicleLoading self.hangarSpace.onVehicleChanged -= self.__onVehicleLoaded self.hangarSpace.onSpaceRefresh -= self.__onSpaceRefresh self.hangarSpace.onSpaceCreate -= self.__onSpaceCreate self.igrCtrl.onIgrTypeChanged -= self.__onIgrTypeChanged self.rankedController.onUpdated -= self.onRankedUpdate self.rankedController.onGameModeStatusTick -= self.__updateAlertMessage self.__mapboxCtrl.onPrimeTimeStatusUpdated -= self.__updateAlertMessage self.__funRandomController.onGameModeStatusUpdated -= self.__updateAlertMessage self.battleRoyaleController.onUpdated -= self.__updateBattleRoyaleComponents self.epicController.onUpdated -= self.__onEpicBattleUpdated self.epicController.onPrimeTimeStatusUpdated -= self.__onEpicBattleUpdated self.epicController.onGameModeStatusTick -= self.__updateAlertMessage self._promoController.onNewTeaserReceived -= self.__onTeaserReceived if self.__teaser is not None: self.__teaser.stop() self.__teaser = None self.hangarSpace.setVehicleSelectable(False) g_prbCtrlEvents.onVehicleClientStateChanged -= self.__onVehicleClientStateChanged unitMgr = prb_getters.getClientUnitMgr() if unitMgr: unitMgr.onUnitJoined -= self.__onUnitJoined g_playerEvents.onPrebattleInvitationAccepted -= self.__onPrebattleInvitationAccepted g_clientUpdateManager.removeObjectCallbacks(self) self._settingsCore.onSettingsChanged -= self.__onSettingsChanged self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingChanged self.__wotPlusInfo.onRenewableSubscriptionDataChanged -= self.__onWotPlusDataChanged self.battlePassController.onSeasonStateChanged -= self.__switchCarousels self.__timer.clearCallbacks() self.__timer = None self.closeHelpLayout() self.stopGlobalListening() self._offersBannerController.hideBanners() LobbySelectableView._dispose(self) return def _updateCnSubscriptionMode(self): toggleGFPanel = self.lobbyContext.getServerSettings( ).isRenewableSubEnabled() self.as_toggleCnSubscriptionS(toggleGFPanel) def _updateBattleRoyaleMode(self): self.as_toggleBattleRoyaleS( g_currentVehicle.isOnlyForBattleRoyaleBattles()) def __updateDogTagsState(self): isDogTagsEnabled = self.lobbyContext.getServerSettings( ).isDogTagEnabled() getTutorialGlobalStorage().setValue(GLOBAL_FLAG.DOGTAGS_ENABLED, isDogTagsEnabled) def __updateWotPlusState(self): isWotPlusGoldEnabled = self.lobbyContext.getServerSettings( ).isRenewableSubGoldReserveEnabled() hasWotPlusActive = BigWorld.player().renewableSubscription.isEnabled() getTutorialGlobalStorage().setValue( GLOBAL_FLAG.WOTPLUS_ENABLED, hasWotPlusActive and isWotPlusGoldEnabled) self._updateCnSubscriptionMode() def __onWindowLoaded(self, uniqueID, newStatus): window = self.gui.windowsManager.getWindow(uniqueID) if window in _HELP_LAYOUT_RESTRICTED_LAYERS and newStatus in ( WindowStatus.LOADING, WindowStatus.LOADED): self.closeHelpLayout() def __switchCarousels(self, force=False): prevCarouselAlias = self.__currentCarouselAlias linkage = HANGAR_ALIASES.TANK_CAROUSEL_UI newCarouselAlias = HANGAR_ALIASES.TANK_CAROUSEL if self.prbDispatcher is not None: if self.prbDispatcher.getFunctionalState().isInPreQueue( QUEUE_TYPE.RANKED): newCarouselAlias = HANGAR_ALIASES.RANKED_TANK_CAROUSEL elif self.prbDispatcher.getFunctionalState().isInPreQueue( QUEUE_TYPE.EPIC) or self.prbDispatcher.getFunctionalState( ).isInUnit(PREBATTLE_TYPE.EPIC): newCarouselAlias = HANGAR_ALIASES.EPICBATTLE_TANK_CAROUSEL elif self.battleRoyaleController.isBattleRoyaleMode(): linkage = HANGAR_ALIASES.BR_TANK_CAROUSEL_UI newCarouselAlias = HANGAR_ALIASES.ROYALE_TANK_CAROUSEL elif self.__mapboxCtrl.isMapboxMode(): newCarouselAlias = HANGAR_ALIASES.MAPBOX_TANK_CAROUSEL elif self.__funRandomController.isFunRandomPrbActive(): newCarouselAlias = HANGAR_ALIASES.FUN_RANDOM_TANK_CAROUSEL elif self.battlePassController.isVisible( ) and self.battlePassController.isValidBattleType( self.prbDispatcher.getEntity()): newCarouselAlias = HANGAR_ALIASES.BATTLEPASS_TANK_CAROUSEL if prevCarouselAlias != newCarouselAlias or force: self.as_setCarouselS(linkage, newCarouselAlias) self.__currentCarouselAlias = newCarouselAlias return def __updateAmmoPanel(self): if self.ammoPanel: self.ammoPanel.update() def __updateParams(self): if self.paramsPanel: self.paramsPanel.update() def __updateVehicleInResearchPanel(self): if self.researchPanel is not None: self.researchPanel.onCurrentVehicleChanged() return def __updateNavigationInResearchPanel(self): if self.prbDispatcher is not None and self.researchPanel is not None: self.researchPanel.setNavigationEnabled( not self.prbDispatcher.getFunctionalState( ).isNavigationDisabled()) return def __updateHeaderComponent(self): if self.headerComponent is not None: self.headerComponent.update() return def __updateRankedHeaderComponent(self): if self.headerComponent is not None: self.headerComponent.updateRankedHeader() return def __updateBattleRoyaleHeaderComponent(self): if self.headerComponent is not None: self.headerComponent.updateBattleRoyaleHeader() return def __updateHeaderEpicWidget(self): if self.epicWidget is not None: self.epicWidget.update() return def __updateCrew(self): if self.crewPanel is not None: self.crewPanel.updateTankmen() return def __updateAlertMessage(self, *_): if self.prbDispatcher is not None: if self.rankedController.isRankedPrbActive(): self.__updateAlertBlock(*self.rankedController.getAlertBlock()) return if self.__funRandomController.isFunRandomPrbActive(): self.__updateAlertBlock( *self.__funRandomController.getAlertBlock()) return if self.__mapboxCtrl.isMapboxPrbActive(): self.__updateMapboxAlertMsg() return if self.epicController.isEpicPrbActive(): self.__updateEpicBattleAlertMsg() return self.as_setAlertMessageBlockVisibleS(False) return def __updateEpicBattleAlertMsg(self): visible = not self.epicController.isInPrimeTime( ) and self.epicController.isEnabled() data = epic_helpers.getAlertStatusVO() self.__updateAlertBlock(showEpicBattlesPrimeTimeWindow, data, visible) def __updateMapboxAlertMsg(self): status, _, _ = self.__mapboxCtrl.getPrimeTimeStatus() isBlockedStatus = status in (PrimeTimeStatus.NOT_AVAILABLE, PrimeTimeStatus.NOT_SET, PrimeTimeStatus.FROZEN) data = mapbox_helpers.getPrimeTimeStatusVO() self.__updateAlertBlock(shared_events.showMapboxPrimeTimeWindow, data, isBlockedStatus) def __updateAlertBlock(self, callback, data, visible): self.as_setAlertMessageBlockVisibleS(visible) if visible and self.alertMessage is not None: self.alertMessage.update(data.asDict(), onBtnClickCallback=callback) return def __onWaitingShown(self, _): self.closeHelpLayout() def __handleFightButtonUpdated(self, _): self.__updateNavigationInResearchPanel() def __handleSelectedEntityUpdated(self, event): ctx = event.ctx if ctx['state'] != CameraMovementStates.FROM_OBJECT: entity = BigWorld.entities.get(ctx['entityId'], None) if isinstance(entity, HeroTank): descriptor = entity.typeDescriptor if descriptor: marathons = self.__marathonCtrl.getMarathons() vehicleCD = descriptor.type.compactDescr activeMarathon = next((marathon for marathon in marathons if marathon.vehicleID == vehicleCD), None) if activeMarathon: title = backport.text( R.strings.marathon.vehiclePreview.buyingPanel. title()) shared_events.showMarathonVehiclePreview( vehicleCD, activeMarathon.remainingPackedRewards, title, activeMarathon.prefix, True) elif isResourceWellRewardVehicle(vehicleCD=vehicleCD): shared_events.showResourceWellHeroPreview(vehicleCD) else: shared_events.showHeroTankPreview(vehicleCD) self.__checkVehicleCameraState() self.__updateState() return def __onTeaserReceived(self, teaserData, showCallback, closeCallback): if self.__teaser is None: self.__teaser = TeaserViewer(self, showCallback, closeCallback) self.__teaser.show(teaserData, self._promoController.getPromoCount()) return def _highlight3DEntityAndShowTT(self, entity): itemId = entity.selectionId if itemId: self.as_show3DSceneTooltipS(TOOLTIPS_CONSTANTS.ENVIRONMENT, [itemId]) def _fade3DEntityAndHideTT(self, entity): self.as_hide3DSceneTooltipS() def _onRegisterFlashComponent(self, viewPy, alias): super(Hangar, self)._onRegisterFlashComponent(viewPy, alias) if alias == HANGAR_ALIASES.AMMUNITION_PANEL_INJECT: event = viewPy.getOnPanelSectionSelected() event += self.__onOptDeviceClick event = viewPy.getOnEscKeyDown() event += self.onEscape def _onUnregisterFlashComponent(self, viewPy, alias): super(Hangar, self)._onUnregisterFlashComponent(viewPy, alias) if alias == HANGAR_ALIASES.AMMUNITION_PANEL_INJECT and viewPy.getInjectView( ): event = viewPy.getOnPanelSectionSelected() event -= self.__onOptDeviceClick event = viewPy.getOnEscKeyDown() event -= self.onEscape @property def ammoPanel(self): return self.getComponent(HANGAR_ALIASES.AMMUNITION_PANEL) @property def paramsPanel(self): return self.getComponent(HANGAR_ALIASES.VEHICLE_PARAMETERS) @property def crewPanel(self): return self.getComponent(HANGAR_ALIASES.CREW) @property def researchPanel(self): return self.getComponent(HANGAR_ALIASES.RESEARCH_PANEL) @property def headerComponent(self): return self.getComponent(HANGAR_ALIASES.HEADER) @property def alertMessage(self): return self.getComponent(HANGAR_ALIASES.ALERT_MESSAGE_BLOCK) @property def epicWidget(self): return self.getComponent(HANGAR_ALIASES.EPIC_WIDGET) def onCacheResync(self, reason, diff): if diff is not None and GUI_ITEM_TYPE.CREW_BOOKS in diff: self.as_setNotificationEnabledS( crewBooksViewedCache().haveNewCrewBooks()) if reason == CACHE_SYNC_REASON.SHOP_RESYNC: self.__updateAll() return else: if diff is not None and GUI_ITEM_TYPE.VEHICLE in diff and g_currentVehicle.isPresent( ): if g_currentVehicle.item.invID in diff[GUI_ITEM_TYPE.VEHICLE]: self.__updateAmmoPanel() return def onPlayerStateChanged(self, entity, roster, accountInfo): if accountInfo.isCurrentPlayer(): self.__updateState() self.__updateAmmoPanel() def onUnitPlayerStateChanged(self, pInfo): if pInfo.isCurrentPlayer(): self.__onEntityChanged() def onUnitPlayersListChanged(self): self.__updateHeaderComponent() self.__updateHeaderEpicWidget() def onPrbEntitySwitched(self): self.__onEntityChanged() def onEnqueued(self, queueType, *args): self.__onEntityChanged() def onDequeued(self, queueType, *args): self.__onEntityChanged() def onRankedUpdate(self): self.__updateHeaderComponent() self.__updateRankedHeaderComponent() def __updateBattleRoyaleComponents(self): self.__updateHeaderComponent() self.__updateBattleRoyaleHeaderComponent() def __onEpicBattleUpdated(self, *_): self.__updateHeaderComponent() self.__updateHeaderEpicWidget() self.__updateAmmoPanel() self.__updateAlertMessage() def __updateAll(self): Waiting.show('updateVehicle') self.__switchCarousels() self.__updateState() self.__updateAmmoPanel() self.__updateParams() self.__updateVehicleInResearchPanel() self.__updateNavigationInResearchPanel() self.__updateHeaderComponent() self.__updateRankedHeaderComponent() self.__updateHeaderEpicWidget() self.__updateCrew() self.__updateAlertMessage() self.__updateBattleRoyaleComponents() self._updateCnSubscriptionMode() self._updateBattleRoyaleMode() Waiting.hide('updateVehicle') def __onCurrentVehicleChanged(self): Waiting.show('updateVehicle') self.__updateState() self.__updateAmmoPanel() self.__updateParams() self.__updateVehicleInResearchPanel() self.__updateHeaderComponent() self.__updateHeaderEpicWidget() self.__updateCrew() self.as_setNotificationEnabledS( crewBooksViewedCache().haveNewCrewBooks()) self._updateCnSubscriptionMode() self._updateBattleRoyaleMode() Waiting.hide('updateVehicle') def __onSpaceRefresh(self): self.__isSpaceReadyForC11n = False self.__updateState() def __onSpaceCreate(self): self.__isSpaceReadyForC11n = True self.__updateState() def __onVehicleLoading(self): self.__isVehicleReadyForC11n = False self.__updateState() def __onVehicleLoaded(self): self.__isVehicleReadyForC11n = True self.__checkVehicleCameraState() self.__updateState() def __onIgrTypeChanged(self, *args): self.__updateVehicleInResearchPanel() self.__updateHeaderComponent() self.__updateHeaderEpicWidget() self.__updateParams() def __updateState(self): state = g_currentVehicle.getViewState() self.as_setCrewEnabledS(state.isCrewOpsEnabled()) isBattleRoyaleMode = self.battleRoyaleController.isBattleRoyaleMode() isC11nEnabled = self.lobbyContext.getServerSettings( ).isCustomizationEnabled() and state.isCustomizationEnabled( ) and not state.isOnlyForEventBattles( ) and self.__isSpaceReadyForC11n and self.__isVehicleReadyForC11n and self.__isVehicleCameraReadyForC11n and not isBattleRoyaleMode if isC11nEnabled: customizationTooltip = makeTooltip( _ms(backport.text(R.strings.tooltips.hangar.tuning.header())), _ms(backport.text(R.strings.tooltips.hangar.tuning.body()))) else: customizationTooltip = makeTooltip( _ms( backport.text( R.strings.tooltips.hangar.tuning.disabled.header())), _ms( backport.text( R.strings.tooltips.hangar.tuning.disabled.body()))) changeNationVisibility = g_currentVehicle.isPresent( ) and g_currentVehicle.item.hasNationGroup isNationChangeAvailable = g_currentVehicle.isPresent( ) and g_currentVehicle.item.isNationChangeAvailable if changeNationVisibility: if isNationChangeAvailable: changeNationTooltipHeader = R.strings.tooltips.hangar.nationChange.header( ) changeNationTooltipBody = R.strings.tooltips.hangar.nationChange.body( ) else: changeNationTooltipHeader = R.strings.tooltips.hangar.nationChange.disabled.header( ) if g_currentVehicle.item.isBroken: changeNationTooltipBody = R.strings.tooltips.hangar.nationChange.disabled.body.destroyed( ) elif g_currentVehicle.item.isInBattle: changeNationTooltipBody = R.strings.tooltips.hangar.nationChange.disabled.body.inBattle( ) elif g_currentVehicle.item.isInUnit: changeNationTooltipBody = R.strings.tooltips.hangar.nationChange.disabled.body.inSquad( ) else: changeNationTooltipBody = '' if changeNationTooltipBody == '': changeNationTooltip = makeTooltip( _ms(backport.text(changeNationTooltipHeader)), '') else: changeNationTooltip = makeTooltip( _ms(backport.text(changeNationTooltipHeader)), _ms(backport.text(changeNationTooltipBody))) else: changeNationTooltip = '' changeNationIsNew = not AccountSettings.getSettings( NATION_CHANGE_VIEWED) isMaintenanceEnabled = state.isMaintenanceEnabled() isEquipmentEnabled = g_currentVehicle.isPresent( ) and not g_currentVehicle.isEquipmentLocked() if isMaintenanceEnabled and isEquipmentEnabled: maintenanceTooltip = TOOLTIPS.HANGAR_MAINTENANCE else: maintenanceTooltip = TOOLTIPS.HANGAR_MAINTENANCE_DISABLED self.as_setupAmmunitionPanelS({ 'maintenanceEnabled': isMaintenanceEnabled, 'maintenanceTooltip': maintenanceTooltip, 'customizationEnabled': isC11nEnabled, 'customizationTooltip': customizationTooltip, 'changeNationVisible': changeNationVisibility, 'changeNationEnable': isNationChangeAvailable, 'changeNationTooltip': changeNationTooltip, 'changeNationIsNew': changeNationIsNew }) self.as_setControlsVisibleS(state.isUIShown()) def __onEntityChanged(self): self.__updateState() self.__updateAmmoPanel() self.__updateAlertMessage() self.__updateNavigationInResearchPanel() self.__updateHeaderComponent() self.__updateRankedHeaderComponent() self.__updateHeaderEpicWidget() self.__switchCarousels() self.__updateBattleRoyaleComponents() def __isSpecialMode(self): return self.prbDispatcher is not None and self.prbDispatcher.getFunctionalState( ).isInUnit() or self.prbDispatcher.getFunctionalState().isInPreQueue( QUEUE_TYPE.RANKED) or self.prbDispatcher.getFunctionalState( ).isInPreQueue(QUEUE_TYPE.EPIC) def __onVehicleClientStateChanged(self, _): self.__updateAmmoPanel() def __onServerSettingChanged(self, diff): if 'isRegularQuestEnabled' in diff: self.__updateHeaderComponent() self.__updateHeaderEpicWidget() if 'isCustomizationEnabled' in diff or 'isNationChangeEnabled' in diff: self.__updateState() if BATTLE_PASS_CONFIG_NAME in diff: self.__switchCarousels() if Configs.BATTLE_ROYALE_CONFIG.value in diff: self.__updateBattleRoyaleComponents() self.__updateState() self.__switchCarousels(force=True) if Configs.EPIC_CONFIG.value in diff: self.__updateHeaderEpicWidget() self.__updateState() self.__switchCarousels(force=True) if DOG_TAGS_CONFIG in diff: self.__updateDogTagsState() if RENEWABLE_SUBSCRIPTION_CONFIG in diff: self.__updateWotPlusState() def __onSettingsChanged(self, diff): if SETTINGS_SECTIONS.UI_STORAGE in diff: if self.ammoPanel: self.ammoPanel.update() def __onWotPlusDataChanged(self, diff): if 'isEnabled' in diff: self.__updateWotPlusState() def __checkVehicleCameraState(self): vehicleEntity = self.hangarSpace.getVehicleEntity() if vehicleEntity is None: return else: self.__isVehicleCameraReadyForC11n = vehicleEntity.state == CameraMovementStates.ON_OBJECT return def __onOptDeviceClick(self, **kwargs): if self.hangarSpace.spaceLoading(): _logger.warning( 'Optional Device click was not handled (kwargs=%s). HangarSpace is currently loading.', kwargs) elif not self.__isUnitJoiningInProgress: self.as_showSwitchToAmmunitionS() showAmmunitionSetupView(**kwargs) def __onUnitJoined(self, _, __): self.__isUnitJoiningInProgress = False self.__timer.stopCallback(self.__onResetUnitJoiningProgress) def __onPrebattleInvitationAccepted(self, _, __): self.__isUnitJoiningInProgress = True self.__timer.delayCallback(15, self.__onResetUnitJoiningProgress) def __onResetUnitJoiningProgress(self): self.__isUnitJoiningInProgress = False
class WebImageHelper(object): __slots__ = ('__callbackMethod', '__imageUrl', '__callbackDelayer', '__webCache', '__defLocalDirPath') __DEFAULT_TIMEOUT = 10.0 def __init__(self, defLocalDirPath='notifications'): self.__callbackMethod = None self.__imageUrl = '' self.__callbackDelayer = CallbackDelayer() self.__webCache = None self.__defLocalDirPath = defLocalDirPath return @async def getLocalPath(self, imageUrl, callback=lambda x: None): self.__imageUrl = imageUrl self.__callbackMethod = callback self.__webCache = getWebCache() if self.__webCache is None: _logger.error('Failed to get web cache. Using empty image path.') self.__callbackDelayer.destroy() self.__callMethod('') return else: localPath = self.__webCache.get(self.__imageUrl) if localPath is not None: _logger.debug('Got image path %s for url %s', localPath, self.__imageUrl) self.__callbackDelayer.destroy() self.__webCache = None self.__callMethod(str(localPath)) return _logger.debug( 'Failed to get image from web cache by url %s. Downloading initialized.', self.__imageUrl) self.__webCache.loadCustomUrls([self.__imageUrl], self.__defLocalDirPath) self.__webCache.onDownloadFinished += self.__stop self.__callbackDelayer.delayCallback(self.__DEFAULT_TIMEOUT, self.__stop) return def __stop(self): self.__callbackDelayer.destroy() self.__webCache.onDownloadFinished -= self.__stop localPath = self.__webCache.get(self.__imageUrl) or '' _logger.debug('Got image path %s for url %s', localPath, self.__imageUrl) self.__webCache = None self.__callMethod(str(localPath)) return def __onTimer(self): _logger.warning( 'Web Cache download timed out. Failed to load image from url: %s', self.__imageUrl) self.__stop() def __callMethod(self, localPath): callback = self.__callbackMethod self.__callbackMethod = None if callback is not None and callable(callback): callback(localPath) return
class NewYearToyObject(NewYearSelectableObject): __customizableObjectsMgr = dependency.descriptor( ICustomizableObjectsManager) def __init__(self): super(NewYearToyObject, self).__init__() self.__hangingEffectPlayer = None self.__regularEffectPlayer = None self.__animators = {} self.__alphaFadeFashion = None self.__callbackDelayer = None return def onEnterWorld(self, prereqs): if self._selfDestroyCheck(): return super(NewYearToyObject, self).onEnterWorld(prereqs) self.__callbackDelayer = CallbackDelayer() self.__playEffects() if self.minAlpha: self.__alphaFadeFashion = BigWorld.WGAlphaFadeFashion() self.__alphaFadeFashion.minAlpha = self.minAlpha self.__alphaFadeFashion.maxAlphaDist = self.maxAlphaDistance * self.maxAlphaDistance self.model.fashion = self.__alphaFadeFashion if self.appearanceDelay: self.model.visible = False self.__callbackDelayer.delayCallback(self.appearanceDelay, self.__showModel) def onLeaveWorld(self): if self.__hangingEffectPlayer is not None: self.__hangingEffectPlayer.stop() self.__hangingEffectPlayer = None if self.__regularEffectPlayer is not None: self.__regularEffectPlayer.stop() self.__regularEffectPlayer = None for animator in self.__animators.itervalues(): if animator is not None: animator.stop() self.__animators.clear() self.__callbackDelayer.destroy() self.__callbackDelayer = None super(NewYearToyObject, self).onLeaveWorld() return def __playEffects(self): if self.hangingEffectName: self.__hangingEffectPlayer = self.__createEffectPlayer( self.hangingEffectName) if self.__hangingEffectPlayer is not None: self.__hangingEffectPlayer.play(self.model) if self.regularEffectName: self.__regularEffectPlayer = self.__createEffectPlayer( self.regularEffectName) if self.__regularEffectPlayer is not None: self.__regularEffectPlayer.play(self.model) if self.hangingAnimationSequence: self.__spawnAnimationSequence(self.hangingAnimationSequence, isHanging=True) if self.animationSequence: self.__spawnAnimationSequence(self.animationSequence) return def __createEffectPlayer(self, effectName): effect = self.__customizableObjectsMgr.getEffect(effectName) if effect is None: return else: effectPlayer = EffectsListPlayer(effect.effectsList, effect.keyPoints) return effectPlayer def __spawnAnimationSequence(self, resourceName, isHanging=False): if resourceName in self.__animators: _logger.error( 'Unable to start animation sequence, because it is already loaded: "%s"', resourceName) return elif self.model is None: _logger.error( 'Could not spawn animation sequence "%s", because model is not loaded: "%s"', resourceName, self.modelName) return else: self.__animators[resourceName] = None animProps = AnimatorInstanceProperties( loopCount=1, loop=False) if isHanging else AnimatorInstanceProperties() loader = AnimationSequence.Loader(resourceName, self.spaceID, animProps) BigWorld.loadResourceListBG( (loader, ), makeCallbackWeak(self.__onAnimatorLoaded, resourceName)) return def __onAnimatorLoaded(self, resourceName, resourceList): if resourceName in resourceList.failedIDs: _logger.error('animationLoading %s failed', resourceName) return animator = resourceList[resourceName] animator.bindTo( AnimationSequence.ModelWrapperContainer(self.model, self.spaceID)) animator.start() self.__animators[resourceName] = animator self.__callbackDelayer.delayCallback(0, self.__checkAnimatorFinish) def __showModel(self): self.__appearanceDelayCallbackId = None self.model.visible = True return def __checkAnimatorFinish(self): for animatorKey, animator in self.__animators.items(): if animator is not None and not animator.isPlaying(): self.__animators.pop(animatorKey) return 0 if self.__animators else None
class DailyQuestWidget(InjectComponentAdaptor, DailyQuestMeta, IGlobalListener): lobbyContext = dependency.descriptor(ILobbyContext) eventsCache = dependency.descriptor(IEventsCache) promoController = dependency.descriptor(IPromoController) __layout = 0 def updateWidgetLayout(self, value): self.__layout = value if self._injectView is not None: self._injectView.setLayout(self.__layout) return def onPrbEntitySwitched(self): if not (self._isRandomBattleSelected() or self._isMapboxSelected()): self.__animateHide() else: self.__showOrHide() def _populate(self): super(DailyQuestWidget, self)._populate() self.__addListeners() self.__timer = CallbackDelayer() self.__showOrHide() def _onPopulate(self): pass def _dispose(self): self.__timer.clearCallbacks() self.__removeListeners() super(DailyQuestWidget, self)._dispose() def _makeInjectView(self): return DailyQuestsWidgetView() def _isRandomBattleSelected(self): return self.__isQueueSelected(QUEUE_TYPE.RANDOMS) def _isMapboxSelected(self): return self.__isQueueSelected(QUEUE_TYPE.MAPBOX) def __isQueueSelected(self, queueType): return self.prbDispatcher.getFunctionalState().isQueueSelected( queueType) if self.prbDispatcher is not None else False def __show(self): if self._injectView is None: self._createInjectView() self._injectView.setVisible(True) self._injectView.viewModel.onDisappear += self.__hide return def __animateHide(self): if self._injectView is not None: self._injectView.setVisible(False) return def __hide(self): if self._injectView is not None: self._injectView.viewModel.onDisappear -= self.__hide self._destroyInjected() return def __delayedShowOrHide(self): self.__timer.delayCallback(UtilsManager.ONE_SECOND, self.__showOrHide) def __showOrHide(self): if not self.__timer.hasDelayedCallback(self.__executeShowOrHide): self.__timer.delayCallback(0.0, self.__executeShowOrHide) def __executeShowOrHide(self): isEnabled = False if self.__shouldHide(): self.__hide() elif self.__hasIncompleteQuests() or self.__hasQuestStatusChanged(): isEnabled = True self.__show() self.as_setEnabledS(isEnabled) def __shouldHide(self): return not isDailyQuestsEnable() or self.promoController.isTeaserOpen( ) or not (self._isRandomBattleSelected() or self._isMapboxSelected()) def __hasIncompleteQuests(self): for quest in self.eventsCache.getDailyQuests().values(): if not quest.isCompleted(): return True return False def __hasQuestStatusChanged(self): for quest in self.eventsCache.getDailyQuests().values(): if self.eventsCache.questsProgress.getQuestCompletionChanged( quest.getID()): return True return False def __onServerSettingsChanged(self, diff): if DAILY_QUESTS_CONFIG in diff: self.__showOrHide() def __onTeaserClosed(self): self.__delayedShowOrHide() def __onTeaserShown(self): self.__timer.stopCallback(self.__showOrHide) self.__showOrHide() def __onSyncCompleted(self): self.__showOrHide() def __addListeners(self): self.startGlobalListening() self.lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingsChanged self.eventsCache.onSyncCompleted += self.__onSyncCompleted self.promoController.onTeaserShown += self.__onTeaserShown self.promoController.onTeaserClosed += self.__onTeaserClosed def __removeListeners(self): self.stopGlobalListening() self.lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingsChanged self.eventsCache.onSyncCompleted -= self.__onSyncCompleted self.promoController.onTeaserShown -= self.__onTeaserShown self.promoController.onTeaserClosed -= self.__onTeaserClosed if self._injectView is not None: self._injectView.viewModel.onDisappear -= self.__hide return
class PreBattleHintPlugin(HintPanelPlugin): sessionProvider = dependency.descriptor(IBattleSessionProvider) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self, parentObj): super(PreBattleHintPlugin, self).__init__(parentObj) self.__isActive = False self.__hintInQueue = None self.__callbackDelayer = CallbackDelayer() self.__questHintSettings = {} self.__helpHintSettings = {} self.__battleComHintSettings = {} self.__isInDisplayPeriod = False self.__haveReqLevel = False self.__vehicleId = None return @classmethod def isSuitable(cls): guiType = cls.sessionProvider.arenaVisitor.getArenaGuiType() return guiType != ARENA_GUI_TYPE.RANKED and guiType != ARENA_GUI_TYPE.BATTLE_ROYALE def start(self): prbSettings = dict( AccountSettings.getSettings(PRE_BATTLE_HINT_SECTION)) self.__questHintSettings = prbSettings[QUEST_PROGRESS_HINT_SECTION] self.__helpHintSettings = prbSettings[HELP_SCREEN_HINT_SECTION] self.__battleComHintSettings = prbSettings[IBC_HINT_SECTION] HintPanelPlugin._updateCounterOnStart( self.__questHintSettings, PRBSettings.HINT_DAY_COOLDOWN, PRBSettings.HINT_BATTLES_COOLDOWN) self.__isActive = True g_eventBus.addListener(GameEvent.SHOW_BTN_HINT, self.__handleShowBtnHint, scope=EVENT_BUS_SCOPE.GLOBAL) g_eventBus.addListener(GameEvent.HELP_DETAILED, self.__handlePressHelpBtn, scope=EVENT_BUS_SCOPE.BATTLE) g_eventBus.addListener(GameEvent.FULL_STATS_QUEST_PROGRESS, self.__handlePressQuestBtn, scope=EVENT_BUS_SCOPE.BATTLE) vStateCtrl = self.sessionProvider.shared.vehicleState if vStateCtrl is not None: vStateCtrl.onVehicleControlling += self.__onVehicleControlling return def stop(self): if not self.isActive(): return else: g_eventBus.removeListener(GameEvent.SHOW_BTN_HINT, self.__handleShowBtnHint, scope=EVENT_BUS_SCOPE.GLOBAL) g_eventBus.removeListener(GameEvent.HELP_DETAILED, self.__handlePressHelpBtn, scope=EVENT_BUS_SCOPE.BATTLE) g_eventBus.removeListener(GameEvent.FULL_STATS_QUEST_PROGRESS, self.__handlePressQuestBtn, scope=EVENT_BUS_SCOPE.BATTLE) vStateCtrl = self.sessionProvider.shared.vehicleState if vStateCtrl is not None: vStateCtrl.onVehicleControlling -= self.__onVehicleControlling self.__callbackDelayer.destroy() self.__isActive = False prbHintSettings = dict() prbHintSettings[ QUEST_PROGRESS_HINT_SECTION] = self.__questHintSettings prbHintSettings[HELP_SCREEN_HINT_SECTION] = self.__helpHintSettings prbHintSettings[IBC_HINT_SECTION] = self.__battleComHintSettings AccountSettings.setSettings(PRE_BATTLE_HINT_SECTION, prbHintSettings) return def isActive(self): return self.__isActive def setPeriod(self, period): self.__isInDisplayPeriod = period in (ARENA_PERIOD.PREBATTLE, ARENA_PERIOD.WAITING) if period is ARENA_PERIOD.BATTLE: self._updateCounterOnBattle(self.__questHintSettings) def updateMapping(self): if self.__hintInQueue is not None: self._parentObj.setBtnHint(self.__hintInQueue, self._getHint()) return def _getHint(self): if self.__hintInQueue is CommandMapping.CMD_SHOW_HELP: keyName = getReadableKey(CommandMapping.CMD_SHOW_HELP) pressText = backport.text( R.strings.ingame_gui.helpScreen.hint.press()) hintText = backport.text( R.strings.ingame_gui.helpScreen.hint.description()) return HintData(keyName, pressText, hintText, 0, 0, HintPriority.HELP) if self.__hintInQueue is CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND: keyName = getReadableKey( CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND) pressText = backport.text( R.strings.ingame_gui.battleCommunication.hint.press()) hintText = backport.text( R.strings.ingame_gui.battleCommunication.hint.description()) return HintData(keyName, pressText, hintText, 0, 0, HintPriority.BATTLE_COMMUNICATION) if self.__hintInQueue is CommandMapping.CMD_QUEST_PROGRESS_SHOW: if self.lobbyContext.getServerSettings().isPersonalMissionsEnabled( ): keyName = getReadableKey( CommandMapping.CMD_QUEST_PROGRESS_SHOW) pressText = '' hintText = backport.text( R.strings.ingame_gui.battleProgress.hint.noBindingKey()) if keyName: pressText = backport.text( R.strings.ingame_gui.battleProgress.hint.press()) hintText = backport.text( R.strings.ingame_gui.battleProgress.hint.description()) return HintData(keyName, pressText, hintText, 0, 0, HintPriority.QUESTS) def __onVehicleControlling(self, vehicle): if not self.isActive(): return else: vTypeDesc = vehicle.typeDescriptor vehicleType = vTypeDesc.type.id self.__vehicleId = makeIntCompactDescrByID('vehicle', vehicleType[0], vehicleType[1]) self.__haveReqLevel = vTypeDesc.level >= _HINT_MIN_VEHICLE_LEVEL if vTypeDesc.isWheeledVehicle or vTypeDesc.type.isDualgunVehicleType or vTypeDesc.hasTurboshaftEngine: self.__updateHintCounterOnStart(self.__vehicleId, vehicle, self.__helpHintSettings) if self.__canDisplayHelpHint(vTypeDesc): self.__displayHint(CommandMapping.CMD_SHOW_HELP) return if self.__canDisplayBattleCommunicationHint(): isDisplayed = self.__displayHint( CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND) if isDisplayed: self.__battleComHintSettings = self._updateBattleCounterOnUsed( self.__battleComHintSettings) return if self.__canDisplayQuestHint(): self.__displayHint(CommandMapping.CMD_QUEST_PROGRESS_SHOW) return if self.__hintInQueue is not None: self._parentObj.removeBtnHint(CommandMapping.CMD_SHOW_HELP) self._parentObj.removeBtnHint( CommandMapping.CMD_QUEST_PROGRESS_SHOW) self._parentObj.removeBtnHint( CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND) self.__callbackDelayer.destroy() return def __updateHintCounterOnStart(self, vehicleId, vehicle, setting): if vehicleId not in setting: setting[vehicleId] = { HINTS_LEFT: 1, LAST_DISPLAY_DAY: 0, NUM_BATTLES: 0 } if vehicle.isAlive() and vehicle.isPlayerVehicle: self._updateCounterOnBattle(setting[vehicleId]) HintPanelPlugin._updateCounterOnStart( setting[vehicleId], PRBSettings.HINT_DAY_COOLDOWN, PRBSettings.HINT_BATTLES_COOLDOWN) def __onHintTimeOut(self): self._parentObj.removeBtnHint(self.__hintInQueue) if self.__hintInQueue is CommandMapping.CMD_SHOW_HELP or self.__hintInQueue is CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND: self.__callbackDelayer.delayCallback(_HINT_COOLDOWN, self.__onHintTimeCooldown, self.__hintInQueue) self.__hintInQueue = None return def __canDisplayHelpHint(self, typeDescriptor): return (typeDescriptor.isWheeledVehicle or typeDescriptor.type.isDualgunVehicleType or typeDescriptor.hasTurboshaftEngine ) and self.__isInDisplayPeriod and self._haveHintsLeft( self.__helpHintSettings[self.__vehicleId]) def __canDisplayBattleCommunicationHint(self): settingsCore = dependency.instance(ISettingsCore) battleCommunicationIsEnabled = bool( settingsCore.getSetting( BattleCommStorageKeys.ENABLE_BATTLE_COMMUNICATION)) return self.__isInDisplayPeriod and self._haveHintsLeft( self.__battleComHintSettings ) and self.sessionProvider.arenaVisitor.getArenaGuiType( ) != ARENA_GUI_TYPE.BOOTCAMP and battleCommunicationIsEnabled def __canDisplayQuestHint(self): return self.__isInDisplayPeriod and self._haveHintsLeft( self.__questHintSettings ) and self.__haveReqLevel and self.sessionProvider.arenaVisitor.getArenaGuiType( ) in ARENA_GUI_TYPE.RANDOM_RANGE and self.lobbyContext.getServerSettings( ).isPersonalMissionsEnabled() def __onHintTimeCooldown(self, lastHint): if lastHint == CommandMapping.CMD_SHOW_HELP and self.__canDisplayBattleCommunicationHint( ): isDisplayed = self.__displayHint( CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND) if isDisplayed: self.__battleComHintSettings = self._updateBattleCounterOnUsed( self.__battleComHintSettings) elif (lastHint == CommandMapping.CMD_SHOW_HELP or lastHint == CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND ) and self.__canDisplayQuestHint(): self.__displayHint(CommandMapping.CMD_QUEST_PROGRESS_SHOW) def __displayHint(self, hintType): if self.__isInDisplayPeriod: self.__hintInQueue = hintType self._parentObj.setBtnHint(hintType, self._getHint()) return True return False def __handleShowBtnHint(self, event): if event.ctx.get( 'btnID') == CommandMapping.CMD_SHOW_HELP or event.ctx.get( 'btnID' ) == CommandMapping.CMD_QUEST_PROGRESS_SHOW or event.ctx.get( 'btnID' ) == CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMAND: self.__callbackDelayer.delayCallback(_HINT_TIMEOUT, self.__onHintTimeOut) elif self.__callbackDelayer.hasDelayedCallback(self.__onHintTimeOut): self.__callbackDelayer.stopCallback(self.__onHintTimeOut) def __handlePressHelpBtn(self, event): if self.__hintInQueue == CommandMapping.CMD_SHOW_HELP: self._parentObj.removeBtnHint(CommandMapping.CMD_SHOW_HELP) self.__callbackDelayer.delayCallback(_HINT_COOLDOWN, self.__onHintTimeCooldown, self.__hintInQueue) self.__hintInQueue = None hintStats = self.__helpHintSettings[self.__vehicleId] self.__helpHintSettings[self.__vehicleId] = self._updateCounterOnUsed( hintStats) return def __handlePressQuestBtn(self, event): if self.__hintInQueue == CommandMapping.CMD_QUEST_PROGRESS_SHOW: self._parentObj.removeBtnHint( CommandMapping.CMD_QUEST_PROGRESS_SHOW) self.__hintInQueue = None self.__questHintSettings = self._updateCounterOnUsed( self.__questHintSettings) return
class SeniorityAwardsNotificationView(ViewImpl): __slots__ = ('__delayer', ) __seniorityAwardCtrl = dependency.descriptor(ISeniorityAwardsController) __itemsCache = dependency.descriptor(IItemsCache) __connectionMgr = dependency.descriptor(IConnectionManager) def __init__(self): settings = ViewSettings( R.views.lobby.seniority_awards.SeniorityAwardsNotificationView()) settings.model = SeniorityAwardsNotificationViewModel() super(SeniorityAwardsNotificationView, self).__init__(settings) self.__delayer = CallbackDelayer() @property def viewModel(self): return self.getViewModel() def _initialize(self, *args, **kwargs): super(SeniorityAwardsNotificationView, self)._initialize() self.viewModel.onOpenShopClick += self.__onOpenShopClick self.viewModel.onCloseAction += self.__onClose self.__seniorityAwardCtrl.onUpdated += self.__update self.__itemsCache.onSyncCompleted += self.__update self.__connectionMgr.onDisconnected += self.__onDisconnect AccountSettings.setSessionSettings(SENIORITY_AWARDS_WINDOW_SHOWN, True) timeDelta = self.__getTimeDeltaTillShowLastCall() if timeDelta > 0: self.__delayer.delayCallback(timeDelta + 0.1, self.__updateDate) def _finalize(self): super(SeniorityAwardsNotificationView, self)._finalize() self.viewModel.onOpenShopClick -= self.__onOpenShopClick self.viewModel.onCloseAction -= self.__onClose self.__seniorityAwardCtrl.onUpdated -= self.__update self.__itemsCache.onSyncCompleted -= self.__update self.__connectionMgr.onDisconnected -= self.__onDisconnect self.__delayer.clearCallbacks() def _onLoading(self, *args, **kwargs): super(SeniorityAwardsNotificationView, self)._onLoading(*args, **kwargs) self.__update() def __update(self, *_, **__): if not self.__seniorityAwardCtrl.needShowNotification: self.destroyWindow() return specialCurrency = self.__seniorityAwardCtrl.getSACoin() with self.viewModel.transaction(): self.viewModel.setSpecialCurrencyCount(specialCurrency) self.__updateDate() def __updateDate(self): if self.__getTimeDeltaTillShowLastCall() < 0: self.viewModel.setDate( int(self.__seniorityAwardCtrl.endTimestamp - time_utils.getServerUTCTime())) def __getTimeDeltaTillShowLastCall(self): return self.__seniorityAwardCtrl.showNotificationLastCallTimestamp - time_utils.getServerUTCTime( ) def __onOpenShopClick(self): showShop(getPlayerSeniorityAwardsUrl()) self.destroyWindow() def __onDisconnect(self): AccountSettings.setSessionSettings(SENIORITY_AWARDS_WINDOW_SHOWN, True) self.destroyWindow() def __onClose(self): self.destroyWindow()
class DynSquadHintPlugin(HintPanelPlugin): sessionProvider = dependency.descriptor(IBattleSessionProvider) _HINT_DAY_COOLDOWN = 30 _HINT_BATTLES_COOLDOWN = 10 _HINT_TIMEOUT = 6 def __init__(self, parentObj): super(DynSquadHintPlugin, self).__init__(parentObj) self.__shouldShowHint = False self.__isHintShown = False self.__isDestroyTimerDisplaying = False self.__isObserver = False self.__settings = {} self.__wasDisplayed = False self.__callbackDelayer = None self._isInRecovery = False self._isUnderFire = False self._isInProgressCircle = False return @classmethod def isSuitable(cls): return cls.sessionProvider.arenaVisitor.getArenaGuiType() in ( ARENA_GUI_TYPE.RANDOM, ARENA_GUI_TYPE.EPIC_BATTLE, ARENA_GUI_TYPE.EPIC_RANDOM) def start(self): arenaDP = self.sessionProvider.getArenaDP() if arenaDP is not None: vInfo = arenaDP.getVehicleInfo() self.__isObserver = vInfo.isObserver() vehicleCtrl = self.sessionProvider.shared.vehicleState if vehicleCtrl is not None: vehicleCtrl.onVehicleStateUpdated += self.__onVehicleStateUpdated dynSquads = self.sessionProvider.dynamic.dynSquads if dynSquads is not None: dynSquads.onDynSquadCreatedOrJoined += self.__onDynSquadCreatedOrJoined self.__settings = AccountSettings.getSettings(DYN_SQUAD_HINT_SECTION) self._updateCounterOnStart(self.__settings, self._HINT_DAY_COOLDOWN, self._HINT_BATTLES_COOLDOWN) g_eventBus.addListener(GameEvent.TOGGLE_VOIP_CHANNEL_ENABLED, self.__onToggleVoipChannel, scope=EVENT_BUS_SCOPE.BATTLE) return def stop(self): ctrl = self.sessionProvider.shared.vehicleState if ctrl is not None: ctrl.onVehicleStateUpdated -= self.__onVehicleStateUpdated dynSquads = self.sessionProvider.dynamic.dynSquads if dynSquads is not None: dynSquads.onDynSquadCreatedOrJoined -= self.__onDynSquadCreatedOrJoined if self.__callbackDelayer is not None: self.__callbackDelayer.destroy() if not self.sessionProvider.isReplayPlaying: AccountSettings.setSettings(DYN_SQUAD_HINT_SECTION, self.__settings) g_eventBus.removeListener(GameEvent.TOGGLE_VOIP_CHANNEL_ENABLED, self.__onToggleVoipChannel, scope=EVENT_BUS_SCOPE.BATTLE) return def show(self): self.__shouldShowHint = True self.__updateHint() def hide(self): self.__shouldShowHint = False self.__updateHint() def setPeriod(self, period): if period is ARENA_PERIOD.BATTLE: self._updateCounterOnBattle(self.__settings) def updateMapping(self): if self.__isHintShown: self.__wasDisplayed = False self.__addHint() def _getHint(self): keyName = getReadableKey(CommandMapping.CMD_VOICECHAT_ENABLE) key = getVirtualKey(CommandMapping.CMD_VOICECHAT_ENABLE) hintTextLeft = backport.text( R.strings.ingame_gui.dynamicSquad.hint.voipToggleKeyLeft()) hintTextRight = backport.text( R.strings.ingame_gui.dynamicSquad.hint.voipToggleKeyRight()) return HintData(key, keyName, hintTextLeft, hintTextRight, 0, 0, HintPriority.DYN_SQUAD, False) def __onToggleVoipChannel(self, *args, **kwargs): self._updateCounterOnUsed(self.__settings) self.hide() def __canShowHint(self): if self.__isObserver or self.sessionProvider.isReplayPlaying or self.__wasDisplayed or self.__areOtherIndicatorsShown( ): return False voipMgr = VOIP.getVOIPManager() if voipMgr: if not voipMgr.isVoiceSupported(): return False keyName = getReadableKey(CommandMapping.CMD_VOICECHAT_ENABLE) return False if not keyName else self._haveHintsLeft(self.__settings) def __addHint(self): if not self.__canShowHint(): return else: self._parentObj.setBtnHint(CommandMapping.CMD_VOICECHAT_ENABLE, self._getHint()) self.__isHintShown = True self.__wasDisplayed = True if self.__callbackDelayer is None: self.__callbackDelayer = CallbackDelayer() self.__callbackDelayer.delayCallback(self._HINT_TIMEOUT, self.__onHintTimeOut) return def __removeHint(self): if not self.__isHintShown: return else: self._parentObj.removeBtnHint(CommandMapping.CMD_VOICECHAT_ENABLE) self.__isHintShown = False if self.__callbackDelayer is not None: self.__callbackDelayer.stopCallback(self.__onHintTimeOut) return def __onHintTimeOut(self): self.__shouldShowHint = False self.__updateHint() def __updateHint(self): _logger.debug('Updating dyn squad: hint') if self.__isObserver or self.sessionProvider.isReplayPlaying: return showHint = self.__shouldShowHint and not self.__areOtherIndicatorsShown( ) if not self.__isHintShown and showHint: self.__addHint() elif self.__isHintShown and not showHint: self.__removeHint() def __onDynSquadCreatedOrJoined(self, isCreator, squadID): self.show() def __onVehicleStateUpdated(self, state, value): if state == VEHICLE_VIEW_STATE.RECOVERY: self._isInRecovery = value[0] self.__updateHint() elif state == VEHICLE_VIEW_STATE.PROGRESS_CIRCLE: self._isInProgressCircle = value[1] self.__updateHint() elif state == VEHICLE_VIEW_STATE.UNDER_FIRE: self._isUnderFire = value self.__updateHint() elif state == VEHICLE_VIEW_STATE.DESTROYED: self.__isInDisplayPeriod = False self.__updateHint() def __areOtherIndicatorsShown(self): return self._isUnderFire or self._isInRecovery or self._isInProgressCircle
class DetachedTurret(BigWorld.Entity): allTurrets = list() def __init__(self): self.__vehDescr = vehicles.VehicleDescr(compactDescr=self.vehicleCompDescr) self.filter = BigWorld.WGTurretFilter() self.__detachConfirmationTimer = SynchronousDetachment(self) self.__detachConfirmationTimer.onInit() self.__detachmentEffects = None self.__hitEffects = {TankPartNames.TURRET: None, TankPartNames.GUN: None} self.__reactors = [] self.targetFullBounds = True self.targetCaps = [1] self.__isBeingPulledCallback = None return def reload(self): pass def prerequisites(self): prereqs = [self.__vehDescr.turret['models']['exploded'], self.__vehDescr.gun['models']['exploded']] prereqs += self.__vehDescr.prerequisites() return prereqs def onEnterWorld(self, prereqs): self.model = prereqs[self.__vehDescr.turret['models']['exploded']] self.model.addMotor(BigWorld.Servo(self.matrix)) self.__gunModel = prereqs[self.__vehDescr.gun['models']['exploded']] node = self.model.node(TankNodeNames.GUN_JOINT, Math.Matrix()) node.attach(self.__gunModel) self.__detachConfirmationTimer.onEnterWorld() self.__vehDescr.keepPrereqs(prereqs) turretDescr = self.__vehDescr.turret if self.isUnderWater == 0: self.__detachmentEffects = _TurretDetachmentEffects(self.model, turretDescr['turretDetachmentEffects'], self.isCollidingWithWorld == 1) self.__reactors.append(self.__detachmentEffects) else: self.__detachmentEffects = None self.__hitEffects[TankPartNames.TURRET] = turretHitEffects = _HitEffects(self.model) self.__hitEffects[TankPartNames.GUN] = gunHitEffects = _HitEffects(self.__gunModel) self.__reactors.append(turretHitEffects) self.__reactors.append(gunHitEffects) self.__componentsDesc = (self.__vehDescr.turret, self.__vehDescr.gun) for desc in self.__componentsDesc: desc['hitTester'].loadBspModel() from helpers.CallbackDelayer import CallbackDelayer self.__isBeingPulledCallback = CallbackDelayer() self.__isBeingPulledCallback.delayCallback(self.__checkIsBeingPulled(), self.__checkIsBeingPulled) DetachedTurret.allTurrets.append(self) return def onLeaveWorld(self): DetachedTurret.allTurrets.remove(self) self.__detachConfirmationTimer.cancel() self.__detachConfirmationTimer = None for reactor in self.__reactors: if reactor is not None: reactor.destroy() self.__isBeingPulledCallback.destroy() self.__isBeingPulledCallback = None return def onStaticCollision(self, energy, point, normal): if self.__detachmentEffects is not None: surfaceMaterial = calcSurfaceMaterialNearPoint(point, normal, self.spaceID) effectIdx = surfaceMaterial.effectIdx groundEffect = True distToWater = BigWorld.wg_collideWater(self.position, surfaceMaterial.point) if distToWater != -1: vel = Math.Vector3(self.velocity).length if vel < _MIN_COLLISION_SPEED: groundEffect = False effectIdx = material_kinds.EFFECT_MATERIAL_INDEXES_BY_NAMES['water'] self.__detachmentEffects.notifyAboutCollision(energy, point, effectIdx, groundEffect, self.isUnderWater) return def showDamageFromShot(self, points, effectsIndex): maxHitEffectCode, decodedPoints = DamageFromShotDecoder.decodeHitPoints(points, self.__vehDescr) for shotPoint in decodedPoints: hitEffects = self.__hitEffects.get(shotPoint.componentName) if hitEffects is not None: hitEffects.showHit(shotPoint, effectsIndex) else: LOG_ERROR("Detached turret got hit into %s component, but it's impossible" % shotPoint.componentName) return def collideSegment(self, startPoint, endPoint, skipGun = False): res = None filterMethod = getattr(self.filter, 'segmentMayHitEntity', lambda : True) if not filterMethod(startPoint, endPoint, 0): return res else: modelsToCheck = (self.model,) if skipGun else (self.model, self.__gunModel) for model, desc in zip(modelsToCheck, self.__componentsDesc): toModel = Matrix(model.matrix) toModel.invert() collisions = desc['hitTester'].localHitTest(toModel.applyPoint(startPoint), toModel.applyPoint(endPoint)) if collisions is None: continue for dist, _, hitAngleCos, matKind in collisions: if res is None or res.dist >= dist: matInfo = desc['materials'].get(matKind) res = SegmentCollisionResult(dist, hitAngleCos, matInfo.armor if matInfo is not None else 0) return res def set_isUnderWater(self, prev): if self.__detachmentEffects is not None: if self.isUnderWater: self.__detachmentEffects.stopEffects() return def set_isCollidingWithWorld(self, prev): pass def changeAppearanceVisibility(self, isVisible): self.model.visible = isVisible self.model.visibleAttachments = isVisible def __checkIsBeingPulled(self): if self.__detachmentEffects is not None: if self.isCollidingWithWorld and not self.isUnderWater and self.velocity.lengthSquared > 0.1: extent = Math.Matrix(self.model.bounds).applyVector(Math.Vector3(0.5, 0.5, 0.5)).length surfaceMaterial = calcSurfaceMaterialNearPoint(self.position, Math.Vector3(0, extent, 0), self.spaceID) self.__detachmentEffects.notifyAboutBeingPulled(True, surfaceMaterial.effectIdx) if surfaceMaterial.matKind == 0: LOG_ERROR('calcSurfaceMaterialNearPoint failed to find the collision point') else: self.__detachmentEffects.notifyAboutBeingPulled(False, None) return SERVER_TICK_LENGTH
class DetachedTurret(BigWorld.Entity, ScriptGameObject): allTurrets = list() collisions = ComponentDescriptor() def __init__(self): ScriptGameObject.__init__(self, self.spaceID) self.__vehDescr = vehicles.VehicleDescr( compactDescr=self.vehicleCompDescr) self.filter = BigWorld.WGTurretFilter() self.__detachConfirmationTimer = SynchronousDetachment(self) self.__detachConfirmationTimer.onInit() self.__detachmentEffects = None self.targetFullBounds = True self.targetCaps = [1] self.__isBeingPulledCallback = None self.__hitEffects = None self.__vehicleStickers = None return def reload(self): pass def __prepareModelAssembler(self): LOG_DEBUG('__prepareModelAssembler', self.__vehDescr.name, self.spaceID) assembler = BigWorld.CompoundAssembler(self.__vehDescr.name, self.spaceID) turretModel, gunModel = self.__getModels() assembler.addRootPart(turretModel, TankPartNames.TURRET) assembler.emplacePart(gunModel, TankNodeNames.GUN_JOINT, TankPartNames.GUN) bspModels = ((TankPartNames.getIdx(TankPartNames.TURRET), self.__vehDescr.turret.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.GUN), self.__vehDescr.gun.hitTester.bspModelName)) collisionAssembler = BigWorld.CollisionAssembler( bspModels, BigWorld.player().spaceID) return [assembler, collisionAssembler] def __getModels(self): outfit = prepareBattleOutfit(self.outfitCD, self.__vehDescr, self.vehicleID) style = outfit.style if style is None: return (self.__vehDescr.turret.models.exploded, self.__vehDescr.gun.models.exploded) else: modelsSetParams = ModelsSetParams(style.modelsSet, ModelStates.EXPLODED, []) _, _, turretModel, gunModel = getPartModelsFromDesc( self.__vehDescr, modelsSetParams) return (turretModel, gunModel) def prerequisites(self): LOG_DEBUG('prerequisites') prereqs = self.__prepareModelAssembler() prereqs += self.__vehDescr.prerequisites() return prereqs def onEnterWorld(self, prereqs): LOG_DEBUG('onEnterWorld', self.__vehDescr.name, self.spaceID) self.model = prereqs[self.__vehDescr.name] self.model.matrix = self.matrix self.collisions = prereqs['collisionAssembler'] self.__detachConfirmationTimer.onEnterWorld() self.__vehDescr.keepPrereqs(prereqs) turretDescr = self.__vehDescr.turret if self.isUnderWater == 0: self.__detachmentEffects = _TurretDetachmentEffects( self.model, turretDescr.turretDetachmentEffects, self.isCollidingWithWorld == 1) self.addComponent(self.__detachmentEffects) else: self.__detachmentEffects = None self.__hitEffects = _HitEffects(self.model) self.addComponent(self.__hitEffects) self.__componentsDesc = (self.__vehDescr.turret, self.__vehDescr.gun) from helpers.CallbackDelayer import CallbackDelayer self.__isBeingPulledCallback = CallbackDelayer() self.__isBeingPulledCallback.delayCallback(self.__checkIsBeingPulled(), self.__checkIsBeingPulled) DetachedTurret.allTurrets.append(self) collisionData = ((TankPartNames.getIdx(TankPartNames.TURRET), self.model.matrix), (TankPartNames.getIdx(TankPartNames.GUN), self.model.node(TankPartNames.GUN))) self.collisions.connect(self.id, ColliderTypes.DYNAMIC_COLLIDER, collisionData) ScriptGameObject.activate(self) return def isAlive(self): return False def removeEdge(self): pass def drawEdge(self): pass def __createAndAttachStickers(self): vehicle = BigWorld.entity(self.vehicleID) if not vehicle: return if self.__vehicleStickers: return self.__vehicleStickers = VehicleStickers( self.__vehDescr, vehicle.publicInfo['marksOnGun']) self.__vehicleStickers.alpha = vehicles.g_cache.commonConfig[ 'miscParams']['damageStickerAlpha'] self.__vehicleStickers.attach(self.model, True, False, True) def onLeaveWorld(self): LOG_DEBUG('onLeaveWorld') ScriptGameObject.deactivate(self) ScriptGameObject.destroy(self) DetachedTurret.allTurrets.remove(self) self.__detachConfirmationTimer.cancel() self.__detachConfirmationTimer = None self.__isBeingPulledCallback.destroy() self.__isBeingPulledCallback = None if self.__vehicleStickers is not None: self.__vehicleStickers.detach() self.__vehicleStickers = None return def onStaticCollision(self, energy, point, normal): if self.__detachmentEffects is not None: surfaceMaterial = calcSurfaceMaterialNearPoint( point, normal, self.spaceID) effectIdx = surfaceMaterial.effectIdx groundEffect = True distToWater = BigWorld.wg_collideWater(self.position, surfaceMaterial.point) collisionPointDest = surfaceMaterial.point - self.position if distToWater != -1 and distToWater <= collisionPointDest.length: vel = Math.Vector3(self.velocity).length if vel < _MIN_COLLISION_SPEED: groundEffect = False effectIdx = material_kinds.EFFECT_MATERIAL_INDEXES_BY_NAMES[ 'water'] self.__detachmentEffects.notifyAboutCollision( energy, point, effectIdx, groundEffect, self.isUnderWater) return def showDamageFromShot(self, points, effectsIndex): _, decodedPoints, _ = DamageFromShotDecoder.decodeHitPoints( points, self.collisions) for shotPoint in decodedPoints: if shotPoint.componentName == TankPartNames.TURRET or shotPoint.componentName == TankPartNames.GUN: self.__hitEffects.showHit(shotPoint, effectsIndex, shotPoint.componentName) LOG_ERROR( "Detached turret got hit into %s component, but it's impossible" % shotPoint.componentName) def set_isUnderWater(self, prev): if self.__detachmentEffects is not None: if self.isUnderWater: self.__detachmentEffects.stopEffects() return def set_isCollidingWithWorld(self, prev): pass def changeAppearanceVisibility(self, isVisible): self.model.visible = isVisible def __checkIsBeingPulled(self): if self.__detachmentEffects is not None: if self.isCollidingWithWorld and not self.isUnderWater and self.velocity.lengthSquared > 0.1: extent = Math.Matrix( self.model.getBoundsForRoot()).applyVector( Math.Vector3(0.5, 0.5, 0.5)).length surfaceMaterial = calcSurfaceMaterialNearPoint( self.position, Math.Vector3(0, extent, 0), self.spaceID) self.__detachmentEffects.notifyAboutBeingPulled( True, surfaceMaterial.effectIdx) if surfaceMaterial.matKind == 0: LOG_ERROR( 'calcSurfaceMaterialNearPoint failed to find the collision point at: ', self.position) else: self.__detachmentEffects.notifyAboutBeingPulled(False, None) return SERVER_TICK_LENGTH
class DailyQuestWidget(InjectComponentAdaptor, DailyQuestMeta, IGlobalListener): lobbyContext = dependency.descriptor(ILobbyContext) eventsCache = dependency.descriptor(IEventsCache) promoController = dependency.descriptor(IPromoController) __layout = 0 def updateWidgetLayout(self, value): self.__layout = value if self._injectView is not None: self._injectView.setLayout(self.__layout) return def onPrbEntitySwitched(self): if not self._isRandomBattleSelected(): if self._injectView is not None: self._injectView.setIsVisible(False) else: self.__showOrHide() return def _populate(self): super(DailyQuestWidget, self)._populate() self.__addListeners() self.__timer = CallbackDelayer() self.__showOrHide() self.__updateHideCallback(EventInfoModel.getDailyProgressResetTimeDelta()) def _dispose(self): self.__timer.clearCallbacks() self.__removeListeners() super(DailyQuestWidget, self)._dispose() def _makeInjectView(self): return DailyQuestsWidgetView() def _isRandomBattleSelected(self): return self.prbDispatcher.getFunctionalState().isQueueSelected(QUEUE_TYPE.RANDOMS) if self.prbDispatcher is not None else False def __show(self): self.as_showWidgetS() if self._injectView is not None: self._injectView.setIsVisible(True) return def __hide(self): self.as_hideWidgetS() if self._injectView is not None: self._injectView.setIsVisible(False) return def __delayedShowOrHide(self): self.__timer.delayCallback(UtilsManager.ONE_SECOND, self.__showOrHide) def __showOrHide(self): if self.__shouldHide(): self.__hide() return if self.__hasUncompletedQuests() or self.__hasQuestStatusChanged(): self.__show() def __shouldHide(self): return not isDailyQuestsEnable() or self.promoController.isTeaserOpen() or not self._isRandomBattleSelected() def __hasUncompletedQuests(self): for quest in self.eventsCache.getDailyQuests().values(): if not quest.isCompleted(): return True return False def __hasQuestStatusChanged(self): for quest in self.eventsCache.getDailyQuests().values(): if self.eventsCache.questsProgress.getQuestCompletionChanged(quest.getID()): return True return False def __onServerSettingsChanged(self, _): self.__showOrHide() def __onTeaserClosed(self): self.__delayedShowOrHide() def __onTeaserShown(self): self.__timer.stopCallback(self.__showOrHide) self.__showOrHide() def __onSyncCompleted(self): self.__showOrHide() def __onNothingToDisplay(self): if self.__shouldHide() or not self.__hasUncompletedQuests(): self.__hide() def __addListeners(self): self.startGlobalListening() self.lobbyContext.getServerSettings().onServerSettingsChange += self.__onServerSettingsChanged self.eventsCache.onSyncCompleted += self.__onSyncCompleted self.promoController.onTeaserShown += self.__onTeaserShown self.promoController.onTeaserClosed += self.__onTeaserClosed if self._injectView is not None: self._injectView.viewModel.onNothingToDisplay += self.__onNothingToDisplay return def __removeListeners(self): self.stopGlobalListening() self.lobbyContext.getServerSettings().onServerSettingsChange -= self.__onServerSettingsChanged self.eventsCache.onSyncCompleted -= self.__onSyncCompleted self.promoController.onTeaserShown -= self.__onTeaserShown self.promoController.onTeaserClosed -= self.__onTeaserClosed if self._injectView is not None: self._injectView.viewModel.onNothingToDisplay -= self.__onNothingToDisplay return def __updateHideCallback(self, countdownValue): self.__timer.delayCallback(countdownValue, self.__hideWidgetOnTimeout) def __hideWidgetOnTimeout(self): if missions_helpers.areCommonQuestsCompleted(self.eventsCache.getDailyQuests().values()): self._injectView.setIsVisible(False)
class TrajectoryViewHintPlugin(HintPanelPlugin): __slots__ = ('__isHintShown', '__isObserver', '__settings', '__callbackDelayer', '__isDestroyTimerDisplaying', '__isDeathZoneTimerDisplaying', '__wasDisplayed') sessionProvider = dependency.descriptor(IBattleSessionProvider) _HINT_DAY_COOLDOWN = 30 _HINT_BATTLES_COOLDOWN = 10 def __init__(self, parentObj): super(TrajectoryViewHintPlugin, self).__init__(parentObj) self.__isHintShown = False self.__isDestroyTimerDisplaying = False self.__isDeathZoneTimerDisplaying = False self.__isObserver = False self.__settings = {} self.__wasDisplayed = False self.__callbackDelayer = CallbackDelayer() @classmethod def isSuitable(cls): return True def start(self): arenaDP = self.sessionProvider.getArenaDP() if arenaDP is not None: vInfo = arenaDP.getVehicleInfo() self.__isObserver = vInfo.isObserver() crosshairCtrl = self.sessionProvider.shared.crosshair if crosshairCtrl is not None: crosshairCtrl.onCrosshairViewChanged += self.__onCrosshairViewChanged crosshairCtrl.onStrategicCameraChanged += self.__onStrategicCameraChanged vehicleCtrl = self.sessionProvider.shared.vehicleState if vehicleCtrl is not None: vehicleCtrl.onVehicleStateUpdated += self.__onVehicleStateUpdated self.__settings = AccountSettings.getSettings( TRAJECTORY_VIEW_HINT_SECTION) self._updateCounterOnStart(self.__settings, self._HINT_DAY_COOLDOWN, self._HINT_BATTLES_COOLDOWN) if crosshairCtrl is not None and vehicleCtrl is not None: self.__setup(crosshairCtrl, vehicleCtrl) return def stop(self): ctrl = self.sessionProvider.shared.crosshair if ctrl is not None: ctrl.onCrosshairViewChanged -= self.__onCrosshairViewChanged ctrl.onStrategicCameraChanged -= self.__onStrategicCameraChanged ctrl = self.sessionProvider.shared.vehicleState if ctrl is not None: ctrl.onVehicleStateUpdated -= self.__onVehicleStateUpdated self.__callbackDelayer.destroy() if not self.sessionProvider.isReplayPlaying: AccountSettings.setSettings(TRAJECTORY_VIEW_HINT_SECTION, self.__settings) return def updateMapping(self): if self.__isHintShown: self.__addHint() def setPeriod(self, period): if period is ARENA_PERIOD.BATTLE: self._updateCounterOnBattle(self.__settings) def __setup(self, crosshairCtrl, vehicleCtrl): self.__onCrosshairViewChanged(crosshairCtrl.getViewID()) self.__onStrategicCameraChanged(crosshairCtrl.getStrategicCameraID()) checkStatesIDs = (VEHICLE_VIEW_STATE.FIRE, VEHICLE_VIEW_STATE.DESTROY_TIMER, VEHICLE_VIEW_STATE.DEATHZONE_TIMER, VEHICLE_VIEW_STATE.STUN) for stateID in checkStatesIDs: stateValue = vehicleCtrl.getStateValue(stateID) if stateValue: self.__onVehicleStateUpdated(stateID, stateValue) def __onCrosshairViewChanged(self, viewID): haveHintsLeft = self._haveHintsLeft(self.__settings) if viewID == CROSSHAIR_VIEW_ID.STRATEGIC and haveHintsLeft: self.__addHint() elif self.__isHintShown: self.__removeHint() def __onStrategicCameraChanged(self, cameraID): cmdMap = CommandMapping.g_instance isUserRequested = cmdMap is not None and cmdMap.isActive( CommandMapping.CMD_CM_TRAJECTORY_VIEW) if isUserRequested: self._updateCounterOnUsed(self.__settings) if isUserRequested and self.__isHintShown: self.__removeHint() return def __onVehicleStateUpdated(self, stateID, stateValue): haveHintsLeft = self._haveHintsLeft(self.__settings) if self.__isHintShown or haveHintsLeft and stateID in _TRAJECTORY_VIEW_HINT_CHECK_STATES: if stateID == VEHICLE_VIEW_STATE.DESTROY_TIMER: self.__isDestroyTimerDisplaying = stateValue.needToShow() elif stateID == VEHICLE_VIEW_STATE.DEATHZONE_TIMER: self.__isDeathZoneTimerDisplaying = stateValue.needToShow() if self.__isHintShown and self.__isThereAnyIndicators(): self.__removeHint() else: ctrl = self.sessionProvider.shared.crosshair if ctrl is not None: self.__onCrosshairViewChanged(ctrl.getViewID()) return def __isThereAnyIndicators(self): if self.__isDestroyTimerDisplaying or self.__isDeathZoneTimerDisplaying: result = True else: ctrl = self.sessionProvider.shared.vehicleState stunInfo = ctrl.getStateValue(VEHICLE_VIEW_STATE.STUN) isVehicleStunned = stunInfo.endTime > 0.0 if stunInfo is not None else False result = ctrl is not None and isVehicleStunned or ctrl.getStateValue( VEHICLE_VIEW_STATE.FIRE) return result def __addHint(self): if self.__isObserver: return if GUI_SETTINGS.spgAlternativeAimingCameraEnabled and not ( self.sessionProvider.isReplayPlaying or self.__isThereAnyIndicators()) and not self.__wasDisplayed: self._parentObj.setBtnHint(CommandMapping.CMD_CM_TRAJECTORY_VIEW, self._getHint()) self.__isHintShown = True self.__wasDisplayed = True self.__callbackDelayer.delayCallback(_HINT_TIMEOUT, self.__onHintTimeOut) def __removeHint(self): if self.__isObserver: return if not self.sessionProvider.isReplayPlaying: self._parentObj.removeBtnHint( CommandMapping.CMD_CM_TRAJECTORY_VIEW) self.__isHintShown = False self.__callbackDelayer.stopCallback(self.__onHintTimeOut) def __onHintTimeOut(self): self.__removeHint() def _getHint(self): hintTextLeft = '' keyName = getReadableKey(CommandMapping.CMD_CM_TRAJECTORY_VIEW) if keyName: hintTextLeft = backport.text( R.strings.ingame_gui.trajectoryView.hint.alternateModeLeft()) hintTextRight = backport.text( R.strings.ingame_gui.trajectoryView.hint.alternateModeRight()) else: hintTextRight = backport.text( R.strings.ingame_gui.trajectoryView.hint.noBindingKey()) return HintData(keyName, hintTextLeft, hintTextRight, _TRAJECTORY_VIEW_HINT_POSITION[0], _TRAJECTORY_VIEW_HINT_POSITION[1], HintPriority.TRAJECTORY)
class SiegeIndicatorHintPlugin(HintPanelPlugin): sessionProvider = dependency.descriptor(IBattleSessionProvider) settingsCore = dependency.descriptor(ISettingsCore) _HINT_DAY_COOLDOWN = 30 _HINT_BATTLES_COOLDOWN = 10 def __init__(self, parentObj): super(SiegeIndicatorHintPlugin, self).__init__(parentObj) self.__isEnabled = False self.__siegeState = _SIEGE_STATE.DISABLED self.__settings = [{}, {}] self.__isHintShown = False self.__isInPostmortem = False self.__isObserver = False self._isInRecovery = False self._isInProgressCircle = False self._isUnderFire = False self.__isWheeledTech = False self.__hasTurboshaftEngine = False self.__period = None self.__isInDisplayPeriod = False self.__callbackDelayer = CallbackDelayer() return @classmethod def isSuitable(cls): return True def start(self): vStateCtrl = self.sessionProvider.shared.vehicleState arenaDP = self.sessionProvider.getArenaDP() self.__settings = [ AccountSettings.getSettings(SIEGE_HINT_SECTION), AccountSettings.getSettings(WHEELED_MODE_HINT_SECTION) ] self._updateCounterOnStart(self.__settings[0], self._HINT_DAY_COOLDOWN, self._HINT_BATTLES_COOLDOWN) self._updateCounterOnStart(self.__settings[1], self._HINT_DAY_COOLDOWN, self._HINT_BATTLES_COOLDOWN) if arenaDP is not None: self.__isObserver = arenaDP.getVehicleInfo().isObserver() else: self.__isObserver = False if vStateCtrl is not None: vStateCtrl.onVehicleStateUpdated += self.__onVehicleStateUpdated vStateCtrl.onVehicleControlling += self.__onVehicleControlling vStateCtrl.onPostMortemSwitched += self.__onPostMortemSwitched vStateCtrl.onRespawnBaseMoving += self.__onRespawnBaseMoving vehicle = vStateCtrl.getControllingVehicle() if vehicle is not None: self.__onVehicleControlling(vehicle) return def stop(self): vStateCtrl = self.sessionProvider.shared.vehicleState if vStateCtrl is not None: vStateCtrl.onVehicleStateUpdated -= self.__onVehicleStateUpdated vStateCtrl.onVehicleControlling -= self.__onVehicleControlling vStateCtrl.onPostMortemSwitched -= self.__onPostMortemSwitched vStateCtrl.onRespawnBaseMoving -= self.__onRespawnBaseMoving AccountSettings.setSettings(SIEGE_HINT_SECTION, self.__settings[0]) AccountSettings.setSettings(WHEELED_MODE_HINT_SECTION, self.__settings[1]) self.__callbackDelayer.destroy() return def updateMapping(self): if not self.__isEnabled: return self.__updateHint() def setPeriod(self, period): if period is ARENA_PERIOD.BATTLE: self.__isInDisplayPeriod = self.__period is not None self._updateCounterOnBattle(self.__settings[self.__isWheeledTech]) self.__period = period if self.__isEnabled: self.__updateHint() return def __onHintUsed(self): self._updateCounterOnUsed(self.__settings[self.__isWheeledTech]) def __updateHint(self): LOG_DEBUG('Updating siege mode: hint') if self.__isInPostmortem or self.__isObserver or self.sessionProvider.isReplayPlaying: return def _showHint(): self._parentObj.setBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION, self._getHint()) self.__isHintShown = True self.__isInDisplayPeriod = False self.__callbackDelayer.delayCallback(_HINT_TIMEOUT, self.__onHintTimeOut) isInSteadyMode = self.__siegeState not in _SIEGE_STATE.SWITCHING haveHintsLeft = self._haveHintsLeft( self.__settings[self.__isWheeledTech]) if isInSteadyMode and self.__isInDisplayPeriod and haveHintsLeft and not self.__areOtherIndicatorsShown( ): _showHint() elif self.__isHintShown or self.__areOtherIndicatorsShown(): self._parentObj.removeBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) self.__isHintShown = False self.__callbackDelayer.destroy() def __onVehicleControlling(self, vehicle): vStateCtrl = self.sessionProvider.shared.vehicleState vTypeDesc = vehicle.typeDescriptor self.__isWheeledTech = vTypeDesc.isWheeledVehicle self.__hasTurboshaftEngine = vTypeDesc.hasTurboshaftEngine if vehicle.isAlive( ) and vTypeDesc.hasSiegeMode and not vTypeDesc.type.isDualgunVehicleType: self.__isEnabled = True state = VEHICLE_VIEW_STATE.SIEGE_MODE value = vStateCtrl.getStateValue(state) if self.__hasTurboshaftEngine: value = (_SIEGE_STATE.ENABLED, None) if value is not None: self.__onVehicleStateUpdated(state, value) else: self.__siegeState = _SIEGE_STATE.DISABLED if self.__isEnabled: self._parentObj.removeBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) self.__isEnabled = False return def __onVehicleStateUpdated(self, state, value): if not self.__isEnabled: return if state == VEHICLE_VIEW_STATE.SIEGE_MODE: siegeState, _ = value if siegeState in _SIEGE_STATE.SWITCHING: if not self.__isObserver and not self.__isInPostmortem: self.__onHintUsed() if self.__siegeState != siegeState: self.__siegeState = siegeState self.__updateHint() elif state == VEHICLE_VIEW_STATE.RECOVERY: self._isInRecovery = value[0] self.__updateHint() elif state == VEHICLE_VIEW_STATE.PROGRESS_CIRCLE: self._isInProgressCircle = value[1] self.__updateHint() elif state == VEHICLE_VIEW_STATE.UNDER_FIRE: self._isUnderFire = value self.__updateHint() elif state == VEHICLE_VIEW_STATE.DESTROYED: self.__isInDisplayPeriod = False self.__updateHint() def __onPostMortemSwitched(self, *args): self.__isInPostmortem = True self._parentObj.removeBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) self.__isHintShown = False def __onRespawnBaseMoving(self): self.__isInPostmortem = False def __updateDestroyed(self, _): self.__isEnabled = False self._parentObj.removeBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) def __onHintTimeOut(self): self._parentObj.removeBtnHint( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) self.__isHintShown = False def _getHint(self): keyName = getReadableKey( CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION) pressText = '' if keyName: pressText = backport.text( R.strings.ingame_gui.siegeMode.hint.press()) if self.__isWheeledTech: hintText = backport.text( R.strings.ingame_gui.siegeMode.hint.wheeled()) elif self.__hasTurboshaftEngine: hintText = backport.text( R.strings.ingame_gui.siegeMode.hint.turboshaftEngine()) else: hintTextID = R.strings.ingame_gui.siegeMode.hint.forMode.dyn( attr='c_{}'.format(self.__siegeState)) hintText = backport.text( hintTextID()) if hintTextID.exists() else None else: hintText = backport.text( R.strings.ingame_gui.siegeMode.hint.noBinding()) return HintData(keyName, pressText, hintText, 0, 0, HintPriority.SIEGE) def __areOtherIndicatorsShown(self): return self._isUnderFire or self._isInRecovery or self._isInProgressCircle
class CrosshairPanelContainer(ExternalFlashComponent, CrosshairPanelContainerMeta): sessionProvider = dependency.descriptor(IBattleSessionProvider) def __init__(self): super(CrosshairPanelContainer, self).__init__(ExternalFlashSettings(BATTLE_VIEW_ALIASES.CROSSHAIR_PANEL, settings.CROSSHAIR_CONTAINER_SWF, settings.CROSSHAIR_ROOT_PATH, settings.CROSSHAIR_INIT_CALLBACK)) self.__plugins = PluginsCollection(self) self.__plugins.addPlugins(plugins.createPlugins()) self.__gunMarkers = None self.__viewID = CROSSHAIR_VIEW_ID.UNDEFINED self.__zoomFactor = 0.0 self.__scale = 1.0 self.__distance = 0 self.__hasAmmo = True self.__callbackDelayer = None self.__isFaded = False return def getViewID(self): return self.__viewID def setViewID(self, viewID): if viewID != self.__viewID: self.__viewID = viewID if self.__gunMarkers is not None: self.__gunMarkers.switch(viewID) chosenSettingID = plugins.chooseSetting(self.__viewID) self.as_setViewS(self.__viewID, chosenSettingID) return def setPosition(self, x, y): self.as_recreateDeviceS(x, y) def getScale(self): return self.__scale def setScale(self, scale): if self.__scale == scale: return else: self.__scale = scale self.as_setScaleS(scale) if self.__gunMarkers is not None: self.__gunMarkers.setScale(scale) return def getZoom(self): return self.__zoomFactor def setZoom(self, zoomFactor): if zoomFactor == self.__zoomFactor: return self.__zoomFactor = zoomFactor if zoomFactor > 1: zoomString = i18n.makeString(INGAME_GUI.AIM_ZOOM, zoom=zoomFactor) else: zoomString = '' self.as_setZoomS(zoomString) def getDistance(self): return self.__distance def setDistance(self, distance): if distance != self.__distance: self.__distance = distance self.as_setDistanceS(i18n.makeString(INGAME_GUI.DISTANCE_METERS, meters=distance)) def clearDistance(self, immediate=True): self.__distance = 0 self.as_clearDistanceS(immediate) def setHasAmmo(self, hasAmmo): if self.__hasAmmo != hasAmmo: self.__hasAmmo = hasAmmo if not hasAmmo: self.as_updateAmmoStateS(i18n.makeString(INGAME_GUI.PLAYER_MESSAGES_POSTMORTEM_USERNOHASAMMO)) else: self.as_updateAmmoStateS('') def setSettings(self, vo): self.as_setSettingsS(vo) def createGunMarkers(self, markersInfo, vehicleInfo): if self.__gunMarkers is not None: LOG_WARNING('Set of gun markers is already created.') return else: self.__setGunMarkers(gm_factory.createComponents(markersInfo, vehicleInfo)) return def invalidateGunMarkers(self, markersInfo, vehicleInfo): if self.__gunMarkers is None: LOG_WARNING('Set of gun markers is not created') return else: newSet = gm_factory.overrideComponents(self.__gunMarkers, markersInfo, vehicleInfo) self.__clearGunMarkers() self.__setGunMarkers(newSet) return def setGunMarkerColor(self, markerType, color): if self.__gunMarkers is None: return False else: component = self.__gunMarkers.getComponentByType(markerType, isActive=True) if component is not None: self.as_setGunMarkerColorS(component.getName(), color) return True def startPlugins(self): if not isPlayerAvatar(): log = _logger.warning if BattleReplay.g_replayCtrl.isPlaying else _logger.error log('Failed to start plugins for %s', self.__class__.__name__) return self.__plugins.start() def stopPlugins(self): self.__clearGunMarkers() self.__plugins.stop() def createExternalComponent(self): super(CrosshairPanelContainer, self).createExternalComponent() self.__configure() def as_playSound(self, value): AutoloaderBoostSoundEvents.play(value) def _populate(self): super(CrosshairPanelContainer, self)._populate() self.__plugins.init() self.startPlugins() g_eventBus.addListener(GameEvent.ROLE_HINT_TOGGLE, self.__handleRoleHintToggled, scope=EVENT_BUS_SCOPE.BATTLE) self.__callbackDelayer = CallbackDelayer() if RoleHelpPlugin.isAvailableToShow(): self.__toggleFade(True) def _dispose(self): self.stopPlugins() self.__plugins.fini() if self.__callbackDelayer: self.__callbackDelayer.destroy() g_eventBus.removeListener(GameEvent.ROLE_HINT_TOGGLE, self.__handleRoleHintToggled, scope=EVENT_BUS_SCOPE.BATTLE) super(CrosshairPanelContainer, self)._dispose() def __handleRoleHintToggled(self, event): self.__toggleFade(event.ctx.get('isShown', False)) def __toggleFade(self, isFaded): if self.__isFaded == isFaded: return self.__isFaded = isFaded if self.__isFaded: self.__callbackDelayer.delayCallback(FADE_TIMEOUT, self.__exceptionalFadeIn) else: self.__callbackDelayer.stopCallback(self.__exceptionalFadeIn) self.as_isFadedS(self.__isFaded) def __exceptionalFadeIn(self): self.__toggleFade(False) _logger.error('as_isFadedS must be called by GameEvent.ROLE_HINT_TOGGLE in __handleRoleHintToggled') def __configure(self): self.component.wg_inputKeyMode = InputKeyMode.NO_HANDLE self.component.position.z = DEPTH_OF_Aim self.component.focus = False self.component.moveFocus = False self.component.heightMode = 'PIXEL' self.component.widthMode = 'PIXEL' self.movie.backgroundAlpha = 0 def __setGunMarkers(self, gunMarkers): self.__gunMarkers = gunMarkers viewSettings = self.__gunMarkers.getViewSettings() LOG_DEBUG('Present view settings of gun markers', viewSettings) for item in viewSettings: if item.hasView: continue if self.as_createGunMarkerS(item.viewID, item.linkage, item.name): self.__gunMarkers.addView(self.component, item.name) LOG_DEBUG('Gun marker has been created', item) LOG_ERROR('Gun marker can not be created', item) self.__gunMarkers.setScale(self.getScale()) self.__gunMarkers.switch(self.getViewID()) def __clearGunMarkers(self): if self.__gunMarkers is None: return else: viewSettings = self.__gunMarkers.getViewSettings() LOG_DEBUG('Previous view settings of gun markers', viewSettings) for item in viewSettings: if not item.hasView: continue if self.as_destroyGunMarkerS(item.name): self.__gunMarkers.removeView(self.component, item.name) LOG_DEBUG('Gun marker has been destroyed', item) self.__gunMarkers.clear() self.__gunMarkers = None return
class CombatEquipmentManager(object): def testArtyStrike(self, id=33, offset=Vector3(0, 0, 0)): if not IS_DEVELOPMENT: return else: p = Vector3(BigWorld.camera().position) d = BigWorld.camera().direction collRes = BigWorld.wg_collideSegment(BigWorld.player().spaceID, p, p + d * 1000, 18, 8) if collRes is None: return strikePos = collRes[0] vDir = Vector2(d.x, d.z) vDir.normalise() self.setEquipmentApplicationPoint(id, strikePos + offset, vDir) return def __init__(self): self.__callbackDelayer = CallbackDelayer() self.__selectedAreas = {} self.__wings = {} self.__isGUIVisible = True if _ENABLE_DEBUG_DRAW: self.debugPolyLine = Flock.DebugPolyLine() self.debugPoints = [] self.debugDirs = [] def onBecomePlayer(self): pass def onBecomeNonPlayer(self): for area in self.__selectedAreas.itervalues(): area.destroy() for wing in self.__wings.itervalues(): wing.destroy() self.__callbackDelayer.destroy() self.__selectedAreas = {} self.__wings = {} def updateBomberTrajectory(self, equipmentID, team, curTime, curPos, curDir, nextTime, nextPos, nextDir, isDroppingPoint): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== updateBomberTrajectory =====') LOG_DEBUG(equipmentID, team) LOG_DEBUG(curPos, curDir, curTime) LOG_DEBUG(nextPos, nextDir, nextTime) LOG_DEBUG(isDroppingPoint) moveDir = nextPos - curPos moveDir.normalise() nextDir3d = Vector3(nextDir.x, moveDir.y, nextDir.y) nextDir3d.normalise() startP = BombersWing.CurveControlPoint(curPos, Vector3(curDir.x, 0, curDir.y), curTime) nextP = BombersWing.CurveControlPoint(nextPos, nextDir3d, nextTime) points = (startP, nextP) wingID = (team, equipmentID) wing = self.__wings.get(wingID) if wing is None or wing.withdrawn: if wing is not None: wing.destroy() self.__wings[wingID] = BombersWing.BombersWing(equipmentID, points) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(curPos) self.debugDirs.append(curDir) else: wing.addControlPoint(points, isDroppingPoint) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(nextPos) self.debugDirs.append(nextDir) self.debugPoints.append(nextPos + Vector3(nextDir.x, 0, nextDir.y) * 10) self.debugPoints.append(nextPos) self.debugPolyLine.set(self.debugPoints) return def showHittingArea(self, equipmentID, pos, dir, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== showHittingArea =====') LOG_DEBUG(equipmentID) LOG_DEBUG(pos, dir, time) correctedCoords = tuple((int(x * 1000.0) for x in pos.tuple())) areaUID = (int(equipmentID), correctedCoords) if areaUID in self.__selectedAreas: return eq = vehicles.g_cache.equipments()[equipmentID] if BattleReplay.isPlaying(): BigWorld.callback( 0.0, functools.partial(self.__showMarkerCallback, eq, pos, dir, time, areaUID)) else: self.__showMarkerCallback(eq, pos, dir, time, areaUID) def __delayedAreaDestroy(self, areaUID): area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() return def __showMarkerCallback(self, eq, pos, dir, time, areaUID): timer = round(time - BigWorld.serverTime()) area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() self.__selectedAreas[areaUID] = self.createEquipmentSelectedArea( pos, dir, eq) area = self.__selectedAreas[areaUID] if area is not None: area.setGUIVisible(self.__isGUIVisible) self.__callbackDelayer.delayCallback( timer, functools.partial(self.__delayedAreaDestroy, areaUID)) ctrl = g_sessionProvider.shared.equipments if ctrl is not None: ctrl.showMarker(eq, pos, dir, timer) return def setGUIVisible(self, isVisible): self.__isGUIVisible = isVisible for area in self.__selectedAreas.itervalues(): area.setGUIVisible(self.__isGUIVisible) @staticmethod def __calcBombsDistribution(bombsCnt, areaWidth, areaLength): coeff = areaWidth / areaLength bombsPerWidth = math.sqrt(bombsCnt * coeff) bombsPerLength = bombsPerWidth / coeff return (bombsPerWidth, bombsPerLength) def showCarpetBombing(self, equipmentID, pos, dir, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG('===== showCarpetBombing =====') LOG_DEBUG(equipmentID) LOG_DEBUG(pos, dir, time) bombEquipment = vehicles.g_cache.equipments()[equipmentID] shellDescr = items.vehicles.getDictDescr( bombEquipment.shellCompactDescr) shotEffect = vehicles.g_cache.shotEffects[shellDescr['effectsIndex']] airstrikeID = shotEffect.get('airstrikeID') if airstrikeID is None: LOG_ERROR('EquipmentID %s has no airstrike shot effect settings' % equipmentID) return else: areaWidth, areaLength = bombEquipment.areaWidth, bombEquipment.areaLength if _ENABLE_DEBUG_LOG: LOG_DEBUG('Ideal', areaWidth, areaLength) beginExplosionPos = BigWorld.wg_collideSegment( BigWorld.player().spaceID, pos, pos + dir * 1000.0, 18) if beginExplosionPos is None: return beginExplosionPos = beginExplosionPos[0] flatDir = Vector3(dir) flatDir.y = 0.0 flatDir.normalise() endDropPoint = pos + flatDir * (areaLength * bombEquipment.waveFraction) endExplosionPos = BigWorld.wg_collideSegment( BigWorld.player().spaceID, endDropPoint, endDropPoint + dir * 1000.0, 18) if endExplosionPos is None: endExplosionPos = beginExplosionPos + flatDir * ( areaLength * bombEquipment.waveFraction) else: endExplosionPos = endExplosionPos[0] areaLength = beginExplosionPos.flatDistTo(endExplosionPos) averageBombCount = bombEquipment.bombsNumber bombsPerWidth, bombsPerLength = CombatEquipmentManager.__calcBombsDistribution( averageBombCount, areaWidth, areaLength) delay = time - BigWorld.serverTime() explosionVelocity = flatDir * bombEquipment.speed partialAirstrikeFunc = functools.partial( BigWorld.PyGroundEffectManager().playAirstrike, airstrikeID, beginExplosionPos, explosionVelocity, areaWidth, areaLength, math.ceil(bombsPerWidth), math.ceil(bombsPerLength)) if _ENABLE_DEBUG_LOG: LOG_DEBUG('delta', delay) LOG_DEBUG('pos, dir', pos, dir) LOG_DEBUG('Params for artyStrike effect', airstrikeID, beginExplosionPos, flatDir, areaWidth, areaLength, bombsPerWidth, bombsPerLength) if delay < 0.0: partialAirstrikeFunc() else: self.__callbackDelayer.delayCallback(delay, partialAirstrikeFunc) if _ENABLE_DEBUG_DRAW: self.debugStartLine = Flock.DebugLine(pos, beginExplosionPos) self.debugEndLine = Flock.DebugLine(endDropPoint, endExplosionPos) self.__callbackDelayer.delayCallback( delay, functools.partial(_DebugFrontLine.launch, beginExplosionPos, endExplosionPos, areaWidth, explosionVelocity)) return def setEquipmentApplicationPoint(self, equipmentID, point, direction): myTeam = BigWorld.player().team wingID = (myTeam, equipmentID) wing = self.__wings.get(wingID) if wing is not None: wing.destroy() del self.__wings[wingID] self.cell.setEquipmentApplicationPoint(equipmentID, point, direction) return @staticmethod def createEquipmentSelectedArea(pos, dir, equipment): area = CombatSelectedArea.CombatSelectedArea() size = Math.Vector2(equipment.areaWidth, equipment.areaLength) visual = equipment.areaVisual color = equipment.areaColor marker = equipment.areaMarker if visual is None: visual = CombatSelectedArea.DEFAULT_RADIUS_MODEL if color is None: color = CombatSelectedArea.COLOR_WHITE if marker is None: pass area.setup(pos, dir, size, visual, color, marker) return area
class AvatarChatKeyHandling(object): settingsCore = dependency.descriptor(ISettingsCore) settingsCache = dependency.descriptor(ISettingsCache) def __init__(self): self.__isEnabled = None self.__callbackDelayer = CallbackDelayer() self.__arePrivateVoiceOverBlocked = False self.__customSoundHandler = { BATTLE_CHAT_COMMAND_NAMES.CANCEL_REPLY: self.__onCommandReceivedCancelReply, BATTLE_CHAT_COMMAND_NAMES.REPLY: self.__onCommandReceivedReply, BATTLE_CHAT_COMMAND_NAMES.SUPPORTING_ALLY: self.__onCommandReceivedSupportingAlly } self.__customSoundHandlerReply = { BATTLE_CHAT_COMMAND_NAMES.ATTENTION_TO_POSITION: self.__onCommandReceivedAttentionToPositionReply } self.__customMatrixProviderGetter = { MarkerType.VEHICLE_MARKER_TYPE: self.__getVehicleMatrixProvider, MarkerType.BASE_MARKER_TYPE: self.__getBaseMatrixProvider, MarkerType.HEADQUARTER_MARKER_TYPE: self.__getHQMatrixProvider, MarkerType.LOCATION_MARKER_TYPE: self.__getLocationMarkerMatrixProvider } return def onBecomePlayer(self): if g_bootcamp.isRunning() or self.__isBattleRoyale(): return self.settingsCore.onSettingsChanged += self.__onSettingsChanged if not self.settingsCache.settings.isSynced(): self.settingsCache.onSyncCompleted += self.__onSettingsReady else: self.__isEnabled = bool( self.settingsCore.getSetting( BattleCommStorageKeys.ENABLE_BATTLE_COMMUNICATION)) if not self.__isEnabled: return self.__activateHandling() def onBecomeNonPlayer(self): if g_bootcamp.isRunning() or self.__isBattleRoyale(): return self.settingsCore.onSettingsChanged -= self.__onSettingsChanged self.settingsCache.onSyncCompleted -= self.__onSettingsReady if not self.__isEnabled: return self.__deactivateHandling() def handleKey(self, isDown, key, mods): calloutCtrl = self.guiSessionProvider.shared.calloutCtrl if not self.__isEnabled or calloutCtrl is None or BattleReplay.g_replayCtrl.isPlaying: return False elif self.__isEpicBattleOverviewMapScreenVisible(): return False cmdMap = CommandMapping.g_instance if cmdMap.isFiredList( (CommandMapping.CMD_CHAT_SHORTCUT_THANKYOU, CommandMapping.CMD_CHAT_SHORTCUT_BACKTOBASE, CommandMapping.CMD_CHAT_SHORTCUT_AFFIRMATIVE, CommandMapping.CMD_CHAT_SHORTCUT_NEGATIVE, CommandMapping.CMD_CHAT_SHORTCUT_HELPME, CommandMapping.CMD_CHAT_SHORTCUT_RELOAD), key ) and self.isVehicleAlive and isDown and not calloutCtrl.isRadialMenuOpened( ): self.guiSessionProvider.handleContexChatCommand(key) return True isGuiControlOn = not self.getForcedGuiControlModeFlags( ) & GUI_CTRL_MODE_FLAG.CURSOR_VISIBLE if cmdMap.isFired( CommandMapping.CMD_CHAT_SHORTCUT_CONTEXT_COMMIT, key ) and self.isVehicleAlive and isDown and isGuiControlOn and not calloutCtrl.isRadialMenuOpened( ): self.guiSessionProvider.handleContexChatCommand(key) return True else: return calloutCtrl.handleCalloutAndRadialMenuKeyPress(key, isDown) def __isBattleRoyale(self): return ARENA_BONUS_TYPE_CAPS.checkAny( self.arena.bonusType, ARENA_BONUS_TYPE_CAPS.BATTLEROYALE) def __activateHandling(self): ctrl = self.guiSessionProvider.shared.feedback if ctrl: ctrl.onReplyFeedbackReceived += self.__onReplyFeedbackReceived ctrl.onStaticMarkerAdded += self.__onStaticMarkerAdded g_messengerEvents.channels.onCommandReceived += self.__onCommandReceived def __deactivateHandling(self): ctrl = self.guiSessionProvider.shared.feedback if ctrl: ctrl.onReplyFeedbackReceived -= self.__onReplyFeedbackReceived ctrl.onStaticMarkerAdded -= self.__onStaticMarkerAdded g_messengerEvents.channels.onCommandReceived -= self.__onCommandReceived self.__callbackDelayer.destroy() def __onSettingsChanged(self, diff): _logger.debug( 'Settings has changed, checking the battle communication.') isEnabled = diff.get(BattleCommStorageKeys.ENABLE_BATTLE_COMMUNICATION) if isEnabled is None or isEnabled == self.__isEnabled: return else: if isEnabled is True: self.__activateHandling() else: self.__deactivateHandling() self.__isEnabled = isEnabled return def __onPrivateVoiceOverBlockedReset(self): self.__arePrivateVoiceOverBlocked = False def __getAdvancedChatCommandData(self, targetID, markerType): advChatCmp = getattr( self.guiSessionProvider.arenaVisitor.getComponentSystem(), 'advancedChatComponent', None) if advChatCmp is None: return else: advChatCmdData = advChatCmp.getCommandDataForTargetIDAndMarkerType( targetID, markerType) return advChatCmdData def __createMatrix(self, position): matrixProvider = Matrix() matrixProvider.translation = position return matrixProvider def __getVehicleIDForCmdSender(self, cmd): arenaDP = self.guiSessionProvider.getCtx().getArenaDP() if arenaDP is None: return else: cmdSenderVehicleID = self.guiSessionProvider.getArenaDP( ).getVehIDBySessionID(cmd.getSenderID()) return cmdSenderVehicleID def __getVehicleMatrixProvider(self, cmd, vehicleID=None): if vehicleID is None: vehicleID = self.__getVehicleIDByCmd(cmd) vehicle = BigWorld.entities.get(vehicleID) if vehicle is None: position = BigWorld.player().arena.positions.get(vehicleID) if position is not None: maxDistance = 600.0 playerVehiclePosition = BigWorld.player( ).getOwnVehiclePosition() if Vector3(position).distSqrTo( playerVehiclePosition) > maxDistance * maxDistance: direction = position - playerVehiclePosition direction.normalise() return createTranslationMatrix(playerVehiclePosition + direction * maxDistance) return createTranslationMatrix(position) return else: return Matrix(vehicle.matrix) def __getObjectivePosition(self, objectID): teamId, baseId = getBaseTeamAndIDFromUniqueID(objectID) position = self.__getBasePosition(teamId, baseId) if position is None: position = self.__getControlPointPosition(objectID) if position is None: position = self.__getSectorBasePosition(objectID) return position def __getBasePosition(self, teamId, baseId): for team, position, number in self.guiSessionProvider.arenaVisitor.type.getTeamBasePositionsIterator( ): if team == teamId and number == baseId: return position return None def __getSectorBasePosition(self, baseID): sectorBaseComp = getattr( self.sessionProvider.arenaVisitor.getComponentSystem(), 'sectorBaseComponent', None) if sectorBaseComp: sectorBase = sectorBaseComp.getSectorBaseById(baseID) if sectorBase: return sectorBase.position return def __getControlPointPosition(self, objectID): for position, number in self.guiSessionProvider.arenaVisitor.type.getControlPointsIterator( ): if number == objectID: return position return None def __getBaseMatrixProvider(self, cmd, targetID=None): if targetID is None: targetID = cmd.getFirstTargetID() position = self.__getObjectivePosition(targetID) if position is None: return else: matrixProvider = self.__createMatrix(position) return matrixProvider def __getHQMatrixProvider(self, cmd, destructibleEntityID=None): destructibleEntityComp = getattr( self.guiSessionProvider.arenaVisitor.getComponentSystem(), 'destructibleEntityComponent', None) if not destructibleEntityComp: return else: if destructibleEntityID is None: destructibleEntityID = cmd.getFirstTargetID() destructibleObj = destructibleEntityComp.getDestructibleEntity( destructibleEntityID) if destructibleObj is None: return matrixProvider = self.__createMatrix(destructibleObj.position) return matrixProvider def __getLocationMarkerMatrixProvider(self, cmd, targetID=None): if cmd is not None: matrixProvider = self.__createMatrix(cmd.getMarkedPosition()) return matrixProvider if targetID is None and cmd is not None: targetID = cmd.getFirstTargetID() locationPointData = g_locationPointManager.getLocationPointData( targetID) if locationPointData is not None: matrixProvider = self.__createMatrix(locationPointData.position) return matrixProvider else: return def __onCommandReceivedCancelReply(self, commandName, cmd): if not cmd.isCancelReply(): return else: cmdSenderVehicleID = self.__getVehicleIDForCmdSender(cmd) if cmdSenderVehicleID != self.playerVehicleID: return notification = cmd.getSoundEventName(True) self.__playSoundNotification(notification, None, True, True) return def __onCommandReceivedReply(self, commandName, cmd): replyToActionName = cmd.getCommandData()['strArg1'] if replyToActionName not in ONE_SHOT_COMMANDS_TO_REPLIES.keys(): return elif replyToActionName in self.__customSoundHandlerReply: self.__customSoundHandlerReply[replyToActionName]( replyToActionName, cmd) return else: if cmd.hasTarget(): if not cmd.isSender() and not cmd.isReceiver(): return repliedToActionID = BATTLE_CHAT_COMMANDS_BY_NAMES[ replyToActionName].id notificationReply = _ACTIONS.battleChatCommandFromActionID( repliedToActionID).soundNotificationReply if notificationReply is None: _logger.warning( 'notificationReply is None for replyToActionName = %s !- Take a look at messenger_common_chat2.py', replyToActionName) return self.__playSoundNotificationOnCommandReceived( cmd, MarkerType.VEHICLE_MARKER_TYPE, True, notificationReply) return def __onCommandReceivedSupportingAlly(self, commandName, cmd): enableVoice = True if cmd.hasTarget() and not cmd.isSender() and not cmd.isReceiver(): enableVoice = False markerType = _COMMAND_NAME_TRANSFORM_MARKER_TYPE.get( commandName, MarkerType.VEHICLE_MARKER_TYPE) self.__playSoundNotificationOnCommandReceived(cmd, markerType, True, None, enableVoice) return def __onCommandReceivedAttentionToPositionReply(self, replyToActionName, cmd): repliedToActionID = BATTLE_CHAT_COMMANDS_BY_NAMES[replyToActionName].id notificationReply = _ACTIONS.battleChatCommandFromActionID( repliedToActionID).soundNotificationReply if notificationReply is None: _logger.warning( 'soundNotificationReply is None for replyToActionName %s! - Take a look at messenger_common_chat2.py', replyToActionName) return else: self.__playSoundNotificationOnCommandReceived( cmd, MarkerType.VEHICLE_MARKER_TYPE, True, notificationReply) return def __onStaticMarkerAdded(self, areaID, creatorID, position, markerSymbolName, markerText='', numberOfReplies=0, isTargetForPlayer=False): originalCmdId = self.__getOriginalCommandID( areaID, MarkerType.LOCATION_MARKER_TYPE) if originalCmdId <= 0: return else: command = _ACTIONS.battleChatCommandFromActionID(originalCmdId) if not command: return notification = command.soundNotification if notification is None: return matrixProvider = self.__createMatrix(position) sentByPlayer = creatorID in ( self.playerVehicleID, self.sessionProvider.arenaVisitor.getArenaUniqueID()) self.__playSoundNotification(notification, matrixProvider.translation, True, sentByPlayer) return def __getOriginalCommandID(self, targetID, markerType): advancedChatCommandData = self.__getAdvancedChatCommandData( targetID, markerType) return None if advancedChatCommandData is None else advancedChatCommandData.command.getID( ) def __onReplyFeedbackReceived(self, targetID, replierID, markerType, oldReplyCount, newReplyCount): if oldReplyCount > newReplyCount: return else: advancedChatCommandData = self.__getAdvancedChatCommandData( targetID, markerType) if advancedChatCommandData is None or advancedChatCommandData.command is None: return senderID = self.__getVehicleIDForCmdSender( advancedChatCommandData.command) if senderID != self.playerVehicleID: if self.playerVehicleID not in advancedChatCommandData.owners: return commandID = advancedChatCommandData.command.getID() soundNotificationReply = _ACTIONS.battleChatCommandFromActionID( commandID).soundNotificationReply if soundNotificationReply is None or markerType not in self.__customMatrixProviderGetter: return if targetID == self.playerVehicleID: matrixProvider = self.__customMatrixProviderGetter[markerType]( None, replierID) else: matrixProvider = self.__customMatrixProviderGetter[markerType]( None, targetID) enableVoice = True if replierID != self.playerVehicleID and targetID != self.playerVehicleID: enableVoice = False sentByPlayer = True if replierID == self.playerVehicleID else False self.__playSoundNotification(soundNotificationReply, matrixProvider.translation, enableVoice, sentByPlayer) return def __onCommandReceived(self, cmd): commandName = _ACTIONS.battleChatCommandFromActionID(cmd.getID()).name if commandName in _SKIP_ON_COMMAND_RECEIVED: return if commandName in self.__customSoundHandler: self.__customSoundHandler[commandName](commandName, cmd) else: markerType = _COMMAND_NAME_TRANSFORM_MARKER_TYPE.get( commandName, MarkerType.VEHICLE_MARKER_TYPE) self.__playSoundNotificationOnCommandReceived( cmd, markerType, True) def __enableVoices(self, enabled, clearQueue=False): if self.soundNotifications: self.soundNotifications.enableVoices(enabled, clearQueue) def __switchSoundFXTo(self, enabled): prevValue = False if self.soundNotifications: prevValue = self.soundNotifications.isCategoryEnabled('fx') self.soundNotifications.enableFX(enabled) return prevValue def __getVehicleIDByCmd(self, cmd): vehicleID = None commandName = _ACTIONS.battleChatCommandFromActionID(cmd.getID()).name if commandName in _TARGET_ID_IS_ENEMY_VEHICLE: vehicleID = cmd.getFirstTargetID() return vehicleID else: if cmd.isReceiver(): vehicleID = self.__getVehicleIDForCmdSender(cmd) elif cmd.isSender(): vehicleID = self.playerVehicleID elif commandName is BATTLE_CHAT_COMMAND_NAMES.SUPPORTING_ALLY: vehicleID = cmd.getFirstTargetID() else: vehicleID = self.__getVehicleIDForCmdSender(cmd) return vehicleID def __getMatrixProvider(self, cmd, markerType): if markerType not in self.__customMatrixProviderGetter: return CommandNotificationData(matrixProvider=None, targetID=None) else: matrixProvider = self.__customMatrixProviderGetter[markerType](cmd) vehicleID = self.__getVehicleIDByCmd(cmd) return CommandNotificationData(matrixProvider=matrixProvider, targetID=vehicleID) def __playSoundNotificationOnCommandReceived(self, cmd, markerType, useSoundNotification=False, notificationName=None, enableVoice=True): if cmd.isEpicGlobalMessage(): if self.soundNotifications: self.soundNotifications.play(EPIC_SOUND.BF_EB_GLOBAL_MESSAGE) else: commandNotificationData = self.__getMatrixProvider(cmd, markerType) if notificationName is None: notificationName = cmd.getSoundEventName(useSoundNotification) if enableVoice is True: if cmd.isReceiver(): if self.__arePrivateVoiceOverBlocked is False: self.__arePrivateVoiceOverBlocked = True self.__callbackDelayer.delayCallback( _PERSONAL_MESSAGE_MUTE_DURATION, self.__onPrivateVoiceOverBlockedReset) else: enableVoice = False _logger.info( 'Voice was blocked for the receiver of a private message due to flood prevention system!' ) cmdSenderVehicleID = self.__getVehicleIDForCmdSender(cmd) sentByPlayer = True if cmdSenderVehicleID == self.playerVehicleID else False self.__playSoundNotification( notificationName, commandNotificationData.matrixProvider.translation, enableVoice, sentByPlayer) return def __resetDebugOutput(self): if self.__debugLine is not None: if BigWorld.player() is not None: BigWorld.player().delModel(self.__debugLine.model) del self.__debugLine self.__debugLine = None return def __drawDebugOutput(self, matrixProvider): self.__resetDebugOutput() if matrixProvider is None: return else: matrixProvider = Matrix(matrixProvider) pos = matrixProvider.translation endPos = matrixProvider.translation endPos.y += 70.0 self.__debugLine = Flock.DebugLine(pos, endPos) self.__debugLine.thickness = 1.0 matrixProvider.translation = pos self.__debugGizmo.setMatrix(matrixProvider) self.__callbackDelayer.delayCallback(4.0, self.__resetDebugOutput) return def __playSoundNotification(self, notification, sndPos=None, enableVoice=True, isSentByPlayer=True): if not self.soundNotifications or notification is None: return else: categoryVoiceIsEnabled = self.soundNotifications.isCategoryEnabled( 'voice') if categoryVoiceIsEnabled and enableVoice is False: self.__enableVoices(enableVoice) playEffect = sndPos is not None or isSentByPlayer prevFxState = self.__switchSoundFXTo(playEffect) if not isSentByPlayer: notification += _IS_NON_PLAYER_NOTIFICATION self.soundNotifications.play(notification, position=sndPos) if categoryVoiceIsEnabled and enableVoice is False: self.__enableVoices(True) if prevFxState != playEffect: self.__switchSoundFXTo(prevFxState) return def __onSettingsReady(self): _logger.debug('Settings are synced, checking the IBC.') self.settingsCache.onSyncCompleted -= self.__onSettingsReady if self.__isEnabled is None: self.__isEnabled = bool( self.settingsCore.getSetting( BattleCommStorageKeys.ENABLE_BATTLE_COMMUNICATION)) if not self.__isEnabled: return self.__activateHandling() return def __isEpicBattleOverviewMapScreenVisible(self): arenaVisitor = self.sessionProvider.arenaVisitor isEpicBattle = arenaVisitor.gui.isInEpicRange() ctrl = self.guiSessionProvider.dynamic.maps return False if not ctrl else isEpicBattle and ctrl.overviewMapScreenVisible
class CombatEquipmentManager(object): def testArtyStrike(self, id=33, offset=Vector3(0, 0, 0)): if not IS_DEVELOPMENT: return else: p = Vector3(BigWorld.camera().position) d = BigWorld.camera().direction collRes = BigWorld.wg_collideSegment( BigWorld.player().spaceID, p, p + d * 1000, 18, lambda matKind, collFlags, itemId, chunkId: collFlags & 8, ) if collRes is None: return strikePos = collRes[0] vDir = Vector2(d.x, d.z) vDir.normalise() self.setEquipmentApplicationPoint(id, strikePos + offset, vDir) return def __init__(self): self.__callbackDelayer = CallbackDelayer() self.__selectedAreas = {} self.__wings = {} if _ENABLE_DEBUG_DRAW: self.debugPolyLine = Flock.DebugPolyLine() self.debugPoints = [] self.debugDirs = [] def onBecomePlayer(self): pass def onBecomeNonPlayer(self): for area in self.__selectedAreas.itervalues(): area.destroy() for wing in self.__wings.itervalues(): wing.destroy() self.__callbackDelayer.destroy() self.__selectedAreas = {} self.__wings = {} def updateBomberTrajectory( self, equipmentID, team, curTime, curPos, curDir, nextTime, nextPos, nextDir, isDroppingPoint ): if _ENABLE_DEBUG_LOG: LOG_DEBUG("===== updateBomberTrajectory =====") LOG_DEBUG(equipmentID, team) LOG_DEBUG(curPos, curDir, curTime) LOG_DEBUG(nextPos, nextDir, nextTime) LOG_DEBUG(isDroppingPoint) moveDir = nextPos - curPos moveDir.normalise() nextDir3d = Vector3(nextDir.x, moveDir.y, nextDir.y) nextDir3d.normalise() startP = BombersWing.CurveControlPoint(curPos, Vector3(curDir.x, 0, curDir.y), curTime) nextP = BombersWing.CurveControlPoint(nextPos, nextDir3d, nextTime) points = (startP, nextP) wingID = (team, equipmentID) wing = self.__wings.get(wingID) if wing is None or wing.withdrawn: if wing is not None: wing.destroy() self.__wings[wingID] = BombersWing.BombersWing(equipmentID, points) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(curPos) self.debugDirs.append(curDir) else: wing.addControlPoint(points, isDroppingPoint) if _ENABLE_DEBUG_DRAW: self.debugPoints.append(nextPos) self.debugDirs.append(nextDir) self.debugPoints.append(nextPos + Vector3(nextDir.x, 0, nextDir.y) * 10) self.debugPoints.append(nextPos) self.debugPolyLine.set(self.debugPoints) return def showHittingArea(self, equipmentID, pos, dir, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG("===== showHittingArea =====") LOG_DEBUG(equipmentID) LOG_DEBUG(pos, dir, time) correctedCoords = tuple((int(x * 1000.0) for x in pos.tuple())) areaUID = (int(equipmentID), correctedCoords) if areaUID in self.__selectedAreas: return eq = vehicles.g_cache.equipments()[equipmentID] if BattleReplay.isPlaying(): BigWorld.callback(0.0, functools.partial(self.__showMarkerCallback, eq, pos, dir, time, areaUID)) else: self.__showMarkerCallback(eq, pos, dir, time, areaUID) def __delayedAreaDestroy(self, areaUID): area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() return def __showMarkerCallback(self, eq, pos, dir, time, areaUID): timer = round(time - BigWorld.serverTime()) area = self.__selectedAreas.pop(areaUID, None) if area is not None: area.destroy() self.__selectedAreas[areaUID] = self.createEquipmentSelectedArea(pos, dir, eq) self.__callbackDelayer.delayCallback(timer, functools.partial(self.__delayedAreaDestroy, areaUID)) g_sessionProvider.getEquipmentsCtrl().showMarker(eq, pos, dir, timer) return @staticmethod def __calcBombsDistribution(bombsCnt, areaWidth, areaLength): coeff = areaWidth / areaLength bombsPerWidth = math.sqrt(bombsCnt * coeff) bombsPerLength = bombsPerWidth / coeff return (bombsPerWidth, bombsPerLength) def showCarpetBombing(self, equipmentID, pos, dir, time): if _ENABLE_DEBUG_LOG: LOG_DEBUG("===== showCarpetBombing =====") LOG_DEBUG(equipmentID) LOG_DEBUG(pos, dir, time) bombEquipment = vehicles.g_cache.equipments()[equipmentID] shellDescr = items.vehicles.getDictDescr(bombEquipment.shellCompactDescr) shotEffect = vehicles.g_cache.shotEffects[shellDescr["effectsIndex"]] airstrikeID = shotEffect.get("airstrikeID") if airstrikeID is None: LOG_ERROR("EquipmentID %s has no airstrike shot effect settings" % equipmentID) return else: areaWidth, areaLength = bombEquipment.areaWidth, bombEquipment.areaLength if _ENABLE_DEBUG_LOG: LOG_DEBUG("Ideal", areaWidth, areaLength) beginExplosionPos = BigWorld.wg_collideSegment(BigWorld.player().spaceID, pos, pos + dir * 1000.0, 18) if beginExplosionPos is None: return beginExplosionPos = beginExplosionPos[0] flatDir = Vector3(dir) flatDir.y = 0.0 flatDir.normalise() endDropPoint = pos + flatDir * (areaLength * bombEquipment.waveFraction) endExplosionPos = BigWorld.wg_collideSegment( BigWorld.player().spaceID, endDropPoint, endDropPoint + dir * 1000.0, 18 ) if endExplosionPos is None: endExplosionPos = beginExplosionPos + flatDir * (areaLength * bombEquipment.waveFraction) else: endExplosionPos = endExplosionPos[0] areaLength = beginExplosionPos.flatDistTo(endExplosionPos) averageBombCount = bombEquipment.bombsNumber bombsPerWidth, bombsPerLength = CombatEquipmentManager.__calcBombsDistribution( averageBombCount, areaWidth, areaLength ) delay = time - BigWorld.serverTime() explosionVelocity = flatDir * bombEquipment.speed partialAirstrikeFunc = functools.partial( BigWorld.PyGroundEffectManager().playAirstrike, airstrikeID, beginExplosionPos, explosionVelocity, areaWidth, areaLength, math.ceil(bombsPerWidth), math.ceil(bombsPerLength), ) if _ENABLE_DEBUG_LOG: LOG_DEBUG("delta", delay) LOG_DEBUG("pos, dir", pos, dir) LOG_DEBUG( "Params for artyStrike effect", airstrikeID, beginExplosionPos, flatDir, areaWidth, areaLength, bombsPerWidth, bombsPerLength, ) if delay < 0.0: partialAirstrikeFunc() else: self.__callbackDelayer.delayCallback(delay, partialAirstrikeFunc) if _ENABLE_DEBUG_DRAW: self.debugStartLine = Flock.DebugLine(pos, beginExplosionPos) self.debugEndLine = Flock.DebugLine(endDropPoint, endExplosionPos) self.__callbackDelayer.delayCallback( delay, functools.partial( _DebugFrontLine.launch, beginExplosionPos, endExplosionPos, areaWidth, explosionVelocity ), ) return def setEquipmentApplicationPoint(self, equipmentID, point, direction): myTeam = BigWorld.player().team wingID = (myTeam, equipmentID) wing = self.__wings.get(wingID) if wing is not None: wing.destroy() del self.__wings[wingID] self.cell.setEquipmentApplicationPoint(equipmentID, point, direction) return @staticmethod def createEquipmentSelectedArea(pos, dir, equipment): area = CombatSelectedArea.CombatSelectedArea() size = Math.Vector2(equipment.areaWidth, equipment.areaLength) visual = equipment.areaVisual color = equipment.areaColor marker = equipment.areaMarker if visual is None: visual = CombatSelectedArea.DEFAULT_RADIUS_MODEL if color is None: color = CombatSelectedArea.COLOR_WHITE if marker is None: pass area.setup(pos, dir, size, visual, color, marker) return area
class DebugDrawEntity(BigWorld.Entity): CUBE_MODEL = 'helpers/models/unit_cube.model' SPHERE_MODEL = 'helpers/models/unit_sphere.model' def __init__(self): super(DebugDrawEntity, self).__init__() self.objectStates = defaultdict(lambda: { 'version': 0, 'models': [], '3Dtexts': [] }) self.reuseModels = defaultdict(list) self.reuse3DTexts = [] self.timer = CallbackDelayer() self.timer.delayCallback(0, self.__onPeriodicCheckTimer, SERVER_TICK_LENGTH) def set_drawObjects(self, prev): objectsToUpdate = [] objectsPresent = [] for drawObject in self.drawObjects: name = drawObject['name'] objectsPresent.append(name) state = self.objectStates[name] if state['version'] != drawObject['version']: for modelName, model, motor in state['models']: self.reuseModels[modelName].append((model, motor)) for textObj in state['3Dtexts']: self.reuse3DTexts.append(textObj) state['models'][:] = [] state['3Dtexts'][:] = [] state['version'] = drawObject['version'] objectsToUpdate.append((state, drawObject)) for key in self.objectStates.keys(): if key not in objectsPresent: state = self.objectStates.pop(key) for modelName, model, motor in state['models']: self.reuseModels[modelName].append((model, motor)) for textObj in state['3Dtexts']: self.reuse3DTexts.append(textObj) for state, draw in objectsToUpdate: for line in draw['lines']: points = line['points'] width = line['width'] for segment in [(points[i - 1], points[i]) for i in xrange(1, len(points))]: obj = self.__createDirectedLine(segment[0], segment[1], width) state['models'].append(obj) for point in points[1:-1]: obj = self.__createSphere(point, (width * 1.25, ) * 3) state['models'].append(obj) for cube in draw['cubes']: obj = self.__createCube(cube['position'], cube['size']) state['models'].append(obj) for sphere in draw['spheres']: obj = self.__createSphere(sphere['position'], sphere['radius']) state['models'].append(obj) for text in draw['texts']: obj = self.__create3DText(text['position'], text['text'], text['color'], text['textSize']) state['3Dtexts'].append(obj) for listOfModels in self.reuseModels.itervalues(): for model, _ in listOfModels: BigWorld.delModel(model) for model, _, _ in self.reuse3DTexts: BigWorld.delModel(model) self.reuseModels.clear() self.reuse3DTexts[:] = [] def onLeaveWorld(self): for _, state in self.objectStates.iteritems(): for _, model, _ in state['models']: BigWorld.delModel(model) for model, _, _ in state['3Dtexts']: BigWorld.delModel(model) for listOfModels in self.reuseModels.itervalues(): for model, _ in listOfModels: BigWorld.delModel(model) for model, _, _ in self.reuse3DTexts: BigWorld.delModel(model) self.timer.destroy() self.timer = None return def __createDirectedLine(self, pointA, pointB, width): modelName = self.CUBE_MODEL model, motor = self.__getModel(modelName) direction = pointB - pointA scale = (width, width, direction.length) rotation = (direction.yaw, direction.pitch, 0) translation = pointA + direction * 0.5 m = mathUtils.createSRTMatrix(scale, rotation, translation) m.preMultiply( mathUtils.createTranslationMatrix(Vector3(0.0, -0.5, 0.0))) motor.signal = m return (modelName, model, motor) def __createCube(self, position, size): modelName = self.CUBE_MODEL model, motor = self.__getModel(modelName) m = mathUtils.createSRTMatrix(size, (0, 0, 0), position) m.preMultiply( mathUtils.createTranslationMatrix(Vector3(0.0, -0.5, 0.0))) motor.signal = m return (modelName, model, motor) def __createSphere(self, position, radius): modelName = self.SPHERE_MODEL model, motor = self.__getModel(modelName) motor.signal = mathUtils.createSRTMatrix(radius, (0, 0, 0), position) return (modelName, model, motor) def __getModel(self, modelName): if self.reuseModels[modelName]: model, motor = self.reuseModels[modelName].pop() else: model = BigWorld.Model(modelName) motor = BigWorld.Servo(Matrix()) model.addMotor(motor) BigWorld.addModel(model, self.spaceID) return (model, motor) def __create3DText(self, position, text, color, textSize): if self.reuse3DTexts: model, motor, component = self.reuse3DTexts.pop() else: attachment = GUI.Attachment() component = GUI.Text(text) attachment.component = component attachment.faceCamera = True motor = BigWorld.Servo(mathUtils.createTranslationMatrix(position)) model = BigWorld.Model('') model.addMotor(motor) BigWorld.addModel(model, self.spaceID) model.root.attach(attachment) component.visible = True component.multiline = True component.explicitSize = True component.filterType = 'LINEAR' component.verticalAnchor = 'BOTTOM' component.text = text component.size = (0, textSize) component.colour = color motor.signal = mathUtils.createTranslationMatrix(position) return (model, motor, component) def __onPeriodicCheckTimer(self, timeSlice): return timeSlice