Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 6
0
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
Exemplo n.º 9
0
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
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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)
Exemplo n.º 15
0
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)
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
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