Пример #1
0
 def onTransitionIn(self):
     import bsInternal
     bs.Activity.onTransitionIn(self)
     bsInternal._addCleanFrameCallback(bs.WeakCall(self._startPreloads))
     self._background = bsUtils.Background(fadeTime=500, startFaded=True, showLogo=False)
     self._part = 1
     self._image = bsUtils.Image(self._tex, transition='fadeIn', modelTransparent=bs.getModel('image4x1'), scale=(800, 200), transitionDelay=500, transitionOutDelay=self._part1Duration-1300)
     bs.gameTimer(self._part1Duration, self.end)
Пример #2
0
    def onTransitionIn(self):
        bs.Activity.onTransitionIn(self)
        global gDidInitialTransition
        random.seed(123)
        try:
            import install
        except ImportError:
            pass
        else:
            # check needed methods
            if hasattr(bs, "get_setting") and hasattr(install,
                                                      "update_modpack"):
                if bs.get_setting("auto-update", False):
                    install.update_modpack(True)
        self._logoNode = None
        self._customLogoTexName = None
        self._wordActors = []
        env = bs.getEnvironment()
        vrMode = bs.getEnvironment()['vrMode']
        if not bs.getEnvironment().get('toolbarTest', True):
            self.myName = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'bottom',
                        'hAlign':
                        'center',
                        'color': (1, 1, 1, 1) if vrMode else (1, 1, 1, 1),
                        'flatness':
                        1.0,
                        'shadow':
                        1.0 if vrMode else 0.5,
                        'scale':
                        (0.65 if (env['interfaceType'] == 'small' or vrMode)
                         else 0.7),  # FIXME need a node attr for this
                        'position': (0, 25),
                        'vrDepth':
                        -10,
                        'text':
                        u'\xa9 2019 Eric Froemling'
                    }))
            fullScreen = bsInternal._getSetting("TV Border")
            if env['interfaceType'] != 'small' or env['vrMode']:
                if fullScreen: position = (0, -10)
                else: position = (-425, 10)
            else:
                if fullScreen: position = (0, -10)
                else: position = (-425, 35)
            self.moderName = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'bottom',
                        'hAlign':
                        'center',
                        'color': (0.8, 0.8, 0.8, 0.8) if vrMode else
                        (0.8, 0.8, 0.8, 0.8),
                        'flatness':
                        1.0,
                        'shadow':
                        1.0 if vrMode else 0.5,
                        'scale': (0.55 if
                                  (env['interfaceType'] == 'small' or vrMode)
                                  else 0.7),  # FIXME need a node attr for this
                        'position':
                        position,
                        'vrDepth':
                        -10,
                        'text':
                        u'\xa9 ModPack is created by Daniil Rakhov'
                    }))

        self._hostIsNavigatingText = bs.NodeActor(
            bs.newNode('text',
                       attrs={
                           'text':
                           bs.Lstr(resource='hostIsNavigatingMenusText',
                                   subs=[
                                       ('${HOST}',
                                        bsInternal._getAccountDisplayString())
                                   ]),
                           'clientOnly':
                           True,
                           'position': (0, -200),
                           'flatness':
                           1.0,
                           'hAlign':
                           'center'
                       }))
        if not gDidInitialTransition:
            if hasattr(self, 'myName'):
                bs.animate(self.myName.node, 'opacity', {2300: 0, 3000: 1.0})
            if hasattr(self, 'moderName'):
                bs.animate(self.moderName.node, 'opacity', {
                    2300: 0,
                    3300: 1.0
                })

        # FIXME - shouldn't be doing things conditionally based on whether
        # the host is vr mode or not (clients may not be or vice versa)
        # - any differences need to happen at the engine level
        # so everyone sees things in their own optimal way
        vrMode = env['vrMode']
        interfaceType = env['interfaceType']

        # in cases where we're doing lots of dev work lets
        # always show the build number
        forceShowBuildNumber = True

        if not bs.getEnvironment().get('toolbarTest', True):
            text = "BROODYs WORLD"
            try:
                from multiversion import get_version
            except ImportError:
                path = os.path.join(env["userScriptsDirectory"],
                                    "about_modpack.json")
                if os.path.exists(path):
                    try:
                        data = json.load(open(path))
                    except Exception:
                        pass
                    else:
                        text += " v." + str(
                            data.get("version", {
                                "v": "???"
                            }).get("v"))
            else:
                text += " v." + str(get_version())
            if env['debugBuild'] or env['testBuild']:
                if env['debugBuild']: text += " [debug]"
                else: text += " [test]"
            if forceShowBuildNumber:
                text = "based on " + str(env['version']) + "\n" + text
            self.version = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'vAttach':
                               'bottom',
                               'hAttach':
                               'right',
                               'hAlign':
                               'right',
                               'flatness':
                               1.0,
                               'vrDepth':
                               -10,
                               'shadow':
                               0.5,
                               'color': (0.5, 0.6, 0.5, 0.7),
                               'scale':
                               0.7 if
                               (interfaceType == 'small' or vrMode) else 0.85,
                               'position': (-260, 10) if vrMode else (-10, 30),
                               'text':
                               text
                           }))
            if not gDidInitialTransition:
                bs.animate(self.version.node, 'opacity', {
                    0: 0,
                    3000: 0,
                    4000: 1.0
                })

        # throw in beta info..
        self.betaInfo = self.betaInfo2 = None
        if env['testBuild'] and not env['kioskMode']:
            self.betaInfo = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'vAttach':
                               'center',
                               'hAlign':
                               'center',
                               'color': (1, 1, 1, 1),
                               'shadow':
                               0.5,
                               'flatness':
                               0.5,
                               'scale':
                               1,
                               'vrDepth':
                               -60,
                               'position': (230, 125) if env['kioskMode'] else
                               (230, 35),
                               'text':
                               bs.Lstr(resource="testBuildText")
                           }))
            if not gDidInitialTransition:
                bs.animate(self.betaInfo.node, 'opacity', {1300: 0, 1800: 1.0})
        model = bs.getModel('thePadLevel')
        treesModel = bs.getModel('trees')
        bottomModel = bs.getModel('thePadLevelBottom')
        borModel = bs.getCollideModel('thePadLevelCollide')
        testColorTexture = bs.getTexture('thePadLevelColor')
        treesTexture = bs.getTexture('treesColor')
        bgTex = bs.getTexture('alwaysLandBGColor')
        bgModel = bs.getModel('alwaysLandBG')
        vrBottomFillModel = bs.getModel('thePadVRFillBottom')
        vrTopFillModel = bs.getModel('thePadVRFillTop')
        bsGlobals = bs.getSharedObject('globals')
        bsGlobals.cameraMode = 'rotate'
        bsGlobals.tint = (1.1, 1.1, 1.0)
        self.bottom = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': bottomModel,
                           'lighting': False,
                           'reflection': 'soft',
                           'reflectionScale': [0.45],
                           'colorTexture': testColorTexture
                       }))
        self.node = bs.newNode('terrain',
                               delegate=self,
                               attrs={
                                   'collideModel':
                                   borModel,
                                   'model':
                                   model,
                                   'colorTexture':
                                   testColorTexture,
                                   'materials':
                                   [bs.getSharedObject('footingMaterial')]
                               })
        self.vrBottomFill = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': vrBottomFillModel,
                           'lighting': False,
                           'vrOnly': True,
                           'colorTexture': testColorTexture
                       }))
        self.vrTopFill = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': vrTopFillModel,
                           'vrOnly': True,
                           'lighting': False,
                           'colorTexture': bgTex
                       }))
        self.terrain = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': model,
                           'colorTexture': testColorTexture,
                           'reflection': 'soft',
                           'reflectionScale': [0.3]
                       }))
        self.trees = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': treesModel,
                           'lighting': False,
                           'reflection': 'char',
                           'reflectionScale': [0.1],
                           'colorTexture': treesTexture
                       }))
        self.bg = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': bgModel,
                           'color': (0.92, 0.91, 0.9),
                           'lighting': False,
                           'background': True,
                           'colorTexture': bgTex
                       }))
        textOffsetV = 0
        self._ts = 0.86
        self._language = None
        self._updateTimer = bs.Timer(2000,
                                     bs.Call(self._update, False),
                                     repeat=True)
        self._update(True)
        bs.gameTimer(55000, bs.Call(self.fireworks))
        bsUtils.animateArray(bs.getSharedObject("globals"), "tint", 3, {0:(1.1,1.1,1.0), 7500:(1.25, 1.21, 1.075), 30000:(1.25, 1.21, 1.075), \
            57500:(1.1, 0.86, 0.74), 67500:(1.1, 0.86, 0.74), \
            90000:(0, 0.27, 0.51), 120000:(0, 0.27, 0.51), 142500:(1.3, 1.06, 1.02), \
            157500:(1.3, 1.06, 1.02), 180000:(1.3, 1.25, 1.2), 195500:(1.3, 1.25, 1.2), \
            220000:(1.1,1.1,1.0)})
        bsInternal._addCleanFrameCallback(bs.WeakCall(self._startPreloads))
        random.seed()

        class News(object):
            def __init__(self, activity):
                self._valid = True
                self._messageDuration = 10000
                self._messageSpacing = 2000
                self._text = None
                self._activity = weakref.ref(activity)
                self._fetchTimer = bs.Timer(1000,
                                            bs.WeakCall(self._tryFetchingNews),
                                            repeat=True)
                self._tryFetchingNews()

            def _tryFetchingNews(self):
                if bsInternal._getAccountState() == 'SIGNED_IN':
                    self._fetchNews()
                    self._fetchTimer = None

            def _fetchNews(self):
                try:
                    launchCount = bs.getConfig()['launchCount']
                except Exception:
                    launchCount = None
                global gLastNewsFetchTime
                gLastNewsFetchTime = time.time()

                # UPDATE - we now just pull news from MRVs
                news = bsInternal._getAccountMiscReadVal('n', None)
                if news is not None:
                    self._gotNews(news)

            def _changePhrase(self):

                global gLastNewsFetchTime

                if time.time() - gLastNewsFetchTime > 100.0:
                    self._fetchNews()
                    self._text = None
                else:
                    if self._text is not None:
                        if len(self._phrases) == 0:
                            for p in self._usedPhrases:
                                self._phrases.insert(0, p)
                        val = self._phrases.pop()
                        if val == '__ACH__':
                            vr = bs.getEnvironment()['vrMode']
                            bsUtils.Text(
                                bs.Lstr(resource='nextAchievementsText'),
                                color=(1,1,1,1) if vr else (0.95,0.9,1,0.4),
                                hostOnly=True,
                                maxWidth=200,
                                position=(-300, -35),
                                hAlign='right',
                                transition='fadeIn',
                                scale=0.9 if vr else 0.7,
                                flatness=1.0 if vr else 0.6,
                                shadow=1.0 if vr else 0.5,
                                hAttach="center",
                                vAttach="top",
                                transitionDelay=1000,
                                transitionOutDelay=self._messageDuration)\
                                   .autoRetain()
                            import bsAchievement
                            achs = [
                                a for a in bsAchievement.gAchievements
                                if not a.isComplete()
                            ]
                            if len(achs) > 0:
                                a = achs.pop(
                                    random.randrange(min(4, len(achs))))
                                a.createDisplay(-180,
                                                -35,
                                                1000,
                                                outDelay=self._messageDuration,
                                                style='news')
                            if len(achs) > 0:
                                a = achs.pop(
                                    random.randrange(min(8, len(achs))))
                                a.createDisplay(180,
                                                -35,
                                                1250,
                                                outDelay=self._messageDuration,
                                                style='news')
                        else:
                            s = self._messageSpacing
                            keys = {
                                s: 0,
                                s + 1000: 1.0,
                                s + self._messageDuration - 1000: 1.0,
                                s + self._messageDuration: 0.0
                            }
                            bs.animate(self._text.node, "opacity",
                                       dict([[k, v] for k, v in keys.items()]))
                            self._text.node.text = val

            def _gotNews(self, news):

                # run this stuff in the context of our activity since we need
                # to make nodes and stuff.. should fix the serverGet call so it
                activity = self._activity()
                if activity is None or activity.isFinalized(): return
                with bs.Context(activity):

                    self._phrases = []
                    # show upcoming achievements in non-vr versions
                    # (currently too hard to read in vr)
                    self._usedPhrases = (
                        ['__ACH__'] if not bs.getEnvironment()['vrMode'] else
                        []) + [s for s in news.split('<br>\n') if s != '']
                    self._phraseChangeTimer = bs.Timer(
                        self._messageDuration + self._messageSpacing,
                        bs.WeakCall(self._changePhrase),
                        repeat=True)

                    sc = 1.2 if (
                        bs.getEnvironment()['interfaceType'] == 'small'
                        or bs.getEnvironment()['vrMode']) else 0.8

                    self._text = bs.NodeActor(
                        bs.newNode(
                            'text',
                            attrs={
                                'vAttach':
                                'top',
                                'hAttach':
                                'center',
                                'hAlign':
                                'center',
                                'vrDepth':
                                -20,
                                'shadow':
                                1.0 if bs.getEnvironment()['vrMode'] else 0.4,
                                'flatness':
                                0.8,
                                'vAlign':
                                'top',
                                'color':
                                ((1, 1, 1,
                                  1) if bs.getEnvironment()['vrMode'] else
                                 (0.7, 0.65, 0.75, 1.0)),
                                'scale':
                                sc,
                                'maxWidth':
                                900.0 / sc,
                                'position': (0, -10)
                            }))
                    self._changePhrase()

        if not env['kioskMode'] and not env.get('toolbarTest', True):
            self._news = News(self)

        # bring up the last place we were, or start at the main menu otherwise
        with bs.Context('UI'):
            try:
                mainWindow = bsUI.gMainWindow
            except Exception:
                mainWindow = None

            # when coming back from a kiosk-mode game, jump to
            # the kiosk start screen.. if bsUtils.gRunningKioskModeGame:
            if bs.getEnvironment()['kioskMode']:
                bsUI.uiGlobals['mainMenuWindow'] = \
                     bsUI.KioskWindow().getRootWidget()
            # ..or in normal cases go back to the main menu
            else:
                if mainWindow == 'Gather':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.GatherWindow(transition=None).getRootWidget()
                elif mainWindow == 'Watch':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.WatchWindow(transition=None).getRootWidget()
                elif mainWindow == 'Team Game Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.TeamsWindow(sessionType=bs.TeamsSession,
                                         transition=None).getRootWidget()
                elif mainWindow == 'Free-for-All Game Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.TeamsWindow(sessionType=bs.FreeForAllSession,
                                         transition=None).getRootWidget()
                elif mainWindow == 'Coop Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.CoopWindow(transition=None).getRootWidget()
                else:                    bsUI.uiGlobals['mainMenuWindow'] = \
                  bsUI.MainMenuWindow(transition=None).getRootWidget()

                # attempt to show any pending offers immediately.
                # If that doesn't work, try again in a few seconds
                # (we may not have heard back from the server)
                # ..if that doesn't work they'll just have to wait
                # until the next opportunity.
                if not bsUI._showOffer():

                    def tryAgain():
                        if not bsUI._showOffer():
                            # try one last time..
                            bs.realTimer(2000, bsUI._showOffer)

                    bs.realTimer(2000, tryAgain)

        gDidInitialTransition = True
Пример #3
0
    def onTransitionIn(self):
        import bsInternal
        bs.Activity.onTransitionIn(self)

        global gDidInitialTransition

        random.seed(123)

        self._logoNode = None
        self._customLogoTexName = None
        
        self._wordActors = []

        env = bs.getEnvironment()
        
        # FIXME - shouldn't be doing things conditionally based on whether the host is vr mode or not
        # (clients may not be or vice versa) - any differences need to happen at the engine level
        # so everyone sees things in their own optimal way
        vrMode = bs.getEnvironment()['vrMode']

        if not bs.getEnvironment().get('toolbarTest',True):
            self.myName = bs.NodeActor(bs.newNode('text',
                                                  attrs={'vAttach':'bottom',
                                                         'hAlign':'center',
                                                         'color':(1.0,1.0,1.0,1.0) if vrMode else (0.5,0.6,0.5,0.6),
                                                         'flatness':1.0,
                                                         'shadow':1.0 if vrMode else 0.5,
                                                         'scale':0.9 if (env['interfaceType'] == 'small' or vrMode) else 0.7, # FIXME need a node attr for this (smallDeviceExtraScale or something)
                                                         'position':(0,10),
                                                         'vrDepth':-10,
                                                         'text':u'\xa9 2016 Eric Froemling'}))

        
        # throw up some text that only clients can see so they know that the host is navigating menus
        # while they're just staring at an empty-ish screen..
        self._hostIsNavigatingText = bs.NodeActor(bs.newNode('text',
                                                      attrs={'text':bs.Lstr(resource='hostIsNavigatingMenusText',subs=[('${HOST}',bsInternal._getAccountDisplayString())]),
                                                             'clientOnly':True,
                                                             'position':(0,-200),
                                                             'flatness':1.0,
                                                             'hAlign':'center'}))

        # print 'TEXT IS',self._hostIsNavigatingText.node.text
        if not gDidInitialTransition and hasattr(self,'myName'):
            bs.animate(self.myName.node,'opacity',{2300:0,3000:1.0})



        # TEMP - test hindi
        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(bs.newNode('text',
                                                 attrs={'vAttach':'center',
                                                        'hAlign':'left',
                                                        'color':(1,1,1,1),
                                                        'shadow':1.0,
                                                        'flatness':0.0,
                                                        'scale':1,
                                                        'position':(-500,-40),
                                                        'text':('\xe0\xa4\x9c\xe0\xa4\xbf\xe0\xa4\xb8 \xe0\xa4\xad\xe0\xa5\x80 \xe0\xa4\x9a\xe0\xa5\x80\xe0\xa5\x9b \xe0\xa4\x95\xe0\xa5\x8b \xe0\xa4\x9b\xe0\xa5\x81\xe0\xa4\x8f\xe0\xa4\x81\xe0\xa4\x97\xe0\xa5\x87 \xe0\xa4\x89\xe0\xa4\xb8\xe0\xa4\xb8\xe0\xa5\x87 \xe0\xa4\x9a\xe0\xa4\xbf\xe0\xa4\xaa\xe0\xa4\x95\n\xe0\xa4\x9c\xe0\xa4\xbe\xe0\xa4\xaf\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\x97\xe0\xa5\x87 .. \xe0\xa4\x87\xe0\xa4\xb8\xe0\xa4\x95\xe0\xa4\xbe \xe0\xa4\xae\xe0\xa5\x9b\xe0\xa4\xbe \xe0\xa4\xb2\xe0\xa5\x87\xe0\xa4\x82 !')}))
        # TEMP - test emoji
        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(bs.newNode('text',
                                                 attrs={'vAttach':'center',
                                                        'hAlign':'left',
                                                        'color':(1,1,1,1),
                                                        'shadow':1.0,
                                                        'flatness':1.0,
                                                        'scale':1,
                                                        'position':(-500,-40),
                                                        'text':('TST: "deivit \xf0\x9f\x90\xa2"')}))
                                                        #'text':('TST: "deivit \xf0\x9f\x90\xa2"')}))

        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(bs.newNode('text',
                                                 attrs={'vAttach':'center',
                                                        'hAlign':'left',
                                                        'color':(1,1,1,1),
                                                        'shadow':1.0,
                                                        'flatness':0.0,
                                                        'scale':1,
                                                        'position':(-500,0),
                                                        #'text':u' \u3147\u3147   \uad8c\ucc2c\uadfc   \uae40\uc6d0\uc7ac\n \ub10c                                            \uc804\uac10\ud638\nlll\u0935\u093f\u0936\u0947\u0937 \u0927\u0928\u094d\u092f\u0935\u093e\u0926:\n'}))
                                                        'text':u'        \u3147\u3147                                         \uad8c\ucc2c\uadfc                                           \uae40\uc6d0\uc7ac\n        \ub10c                                            \uc804\uac10\ud638\nlll\u0935\u093f\u0936\u0947\u0937 \u0927\u0928\u094d\u092f\u0935\u093e\u0926:\n'}))
        # TEMP - test chinese stuff
        if False:
            self.tTest = bs.NodeActor(bs.newNode('text',
                                                 attrs={'vAttach':'center',
                                                        'hAlign':'center',
                                                        'color':(1,1,1,1),
                                                        'shadow':1.0,
                                                        'flatness':0.0,
                                                        'scale':1,
                                                        'position':(-400,-40),
                                                        'text':('TST: "\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n'
                                                                '\xe6\x88\x90\xe5\xb0\xb1\xe4\xb8\xad|         foo\n'
                                                                '\xe8\xb4\xa6\xe6\x88\xb7 \xe7\x99\xbb\xe9\x99\x86foo\n'
                                                                'end"\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n'
                                                                'end"\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n'
                                                                'end2"\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n'
                                                        )}))

        # FIXME - shouldn't be doing things conditionally based on whether the host is vr mode or not
        # (clients may not be or vice versa) - any differences need to happen at the engine level
        # so everyone sees things in their own optimal way
        vrMode = env['vrMode']
        interfaceType = env['interfaceType']

        # in cases where we're doing lots of dev work lets always show the build number
        forceShowBuildNumber = False

        if not bs.getEnvironment().get('toolbarTest',True):
            if env['debugBuild'] or env['testBuild'] or forceShowBuildNumber:
                if env['debugBuild']:
                    #text = bs.Lstr(value='${V} (${B}) (${D})',subs=[('${V}',env['version']),('${B}',str(env['buildNumber'])),('${D}',{'resource':'debugText'})])
                    text = bs.Lstr(value='${V} (${B}) (${D})',subs=[('${V}',env['version']),('${B}',str(env['buildNumber'])),('${D}',bs.Lstr(resource='debugText'))])
                else:
                    # text = bs.Lstr(value='${V} (${B})',subs=[('${V}',env['version']),('${B}',str(env['buildNumber']))])
                    text = bs.Lstr(value='${V} (${B})',subs=[('${V}',env['version']),('${B}',str(env['buildNumber']))])
            else:
                text = bs.Lstr(value='${V}',subs=[('${V}',env['version'])])
            self.version = bs.NodeActor(bs.newNode('text',
                                                   attrs={'vAttach':'bottom',
                                                          'hAttach':'right',
                                                          'hAlign':'right',
                                                          'flatness':1.0,
                                                          'vrDepth':-10,
                                                          'shadow':1.0 if vrMode else 0.5,
                                                          'color':(1,1,1,1) if vrMode else (0.5,0.6,0.5,0.7),
                                                          'scale':0.9 if (interfaceType == 'small' or vrMode) else 0.7,
                                                          'position':(-260,10) if vrMode else (-10,10),
                                                          'text':text
                                                   }))
            if not gDidInitialTransition:
                bs.animate(self.version.node,'opacity',{2300:0,3000:1.0})
            
        # throw in beta info..
        self.betaInfo = self.betaInfo2 = None
        if env['testBuild'] and not env['kioskMode']:
            self.betaInfo = bs.NodeActor(bs.newNode('text',
                                                    attrs={'vAttach':'center',
                                                           'hAlign':'center',
                                                           'color':(1,1,1,1),
                                                           'shadow':0.5,
                                                           'flatness':0.5,
                                                           'scale':1,
                                                           'vrDepth':-60,
                                                           'position':(230,125) if env['kioskMode'] else (230,35),
                                                           'text':bs.Lstr(resource='testBuildText')
                                                    }))
            if not gDidInitialTransition:
                bs.animate(self.betaInfo.node,'opacity',{1300:0,1800:1.0})

            # if not gDidInitialTransition and not env['kioskMode'] and bs.getLanguage() == 'English':
            #     self.betaInfo2 = bs.NodeActor(bs.newNode('text',
            #                                              attrs={'vAttach':'center',
            #                                                     'hAlign':'left',
            #                                                     'color':(1,1,1,1),
            #                                                     'shadow':0.5,
            #                                                     'flatness':0.5,
            #                                                     'scale':0.6,
            #                                                     'position':(177,15),
            #                                                     'text':('Thanks for helping test the game!\n'
            #                                                             +('Note that some features such as GameCenter\n'
            #                                                               'will not function in this build.\n' if 'Mac' in bs.getEnvironment()['userAgentString'] else '')
            #                                                             +'Please email any bugs or other feedback to\n'
            #                                                             '[email protected] or just post it on the\n'
            #                                                             'BombSquad facebook page.\n'
            #                                                             'Enjoy!\n'
            #                                                             '-eric')}))
            #     if not gDidInitialTransition:
            #         bs.animate(self.betaInfo2.node,'opacity',{2300:0,3000:1.0,10000:1.0,11000:0.0})
            

        model = bs.getModel('thePadLevel')
        treesModel = bs.getModel('trees')
        bottomModel = bs.getModel('thePadLevelBottom')
        testColorTexture = bs.getTexture('thePadLevelColor')
        treesTexture = bs.getTexture('treesColor')

        bgTex = bs.getTexture('menuBG')
        bgModel = bs.getModel('thePadBG')

        # (load these last since most platforms don't use them..)
        vrBottomFillModel = bs.getModel('thePadVRFillBottom')
        vrTopFillModel = bs.getModel('thePadVRFillTop')
        
        bsGlobals = bs.getSharedObject('globals')
        
        bsGlobals.cameraMode = 'rotate'

        if False:
            node = bs.newNode('timeDisplay',
                              attrs={'timeMin':2000,
                                     'timeMax':10000,
                                     'showSubSeconds':True})
            self._fooText = bs.NodeActor(bs.newNode('text',
                                                    attrs={'position':(0,-220),
                                                           'flatness':1.0,
                                                           'hAlign':'center'}))
            bsGlobals.connectAttr('gameTime',node,'time2')
            node.connectAttr('output',self._fooText.node,'text')
        
        
        tint = (1.14,1.1,1.0)
        bsGlobals.tint = tint
            
        bsGlobals.ambientColor = (1.06,1.04,1.03)
        bsGlobals.vignetteOuter = (0.45,0.55,0.54)
        bsGlobals.vignetteInner = (0.99,0.98,0.98)

        self.bottom = bs.NodeActor(bs.newNode('terrain',
                                              attrs={'model':bottomModel,
                                                     'lighting':False,
                                                     'reflection':'soft',
                                                     'reflectionScale':[0.45],
                                                     'colorTexture':testColorTexture}))
        self.vrBottomFill = bs.NodeActor(bs.newNode('terrain',
                                                    attrs={'model':vrBottomFillModel,
                                                           'lighting':False,
                                                           'vrOnly':True,
                                                           'colorTexture':testColorTexture}))
        self.vrTopFill = bs.NodeActor(bs.newNode('terrain',
                                                 attrs={'model':vrTopFillModel,
                                                        'vrOnly':True,
                                                        'lighting':False,
                                                        'colorTexture':bgTex}))
        self.terrain = bs.NodeActor(bs.newNode('terrain',
                                               attrs={'model':model,
                                                      'colorTexture':testColorTexture,
                                                      'reflection':'soft',
                                                      'reflectionScale':[0.3]}))
                            

        self.trees = bs.NodeActor(bs.newNode('terrain',
                                             attrs={'model':treesModel,
                                                    'lighting':False,
                                                    'reflection':'char',
                                                    'reflectionScale':[0.1],
                                                    'colorTexture':treesTexture}))

        self.bg = bs.NodeActor(bs.newNode('terrain',
                                          attrs={'model':bgModel,
                                                 'color':(0.92,0.91,0.9),
                                                 'lighting':False,
                                                 'background':True,
                                                 'colorTexture':bgTex}))
        textOffsetV = 0
        self._ts = 0.86

        self._language = None
        self._updateTimer = bs.Timer(1000, self._update, repeat=True)
        self._update()

        # hopefully this won't hitch but lets space these out anyway..
        bsInternal._addCleanFrameCallback(bs.WeakCall(self._startPreloads))

        random.seed()

        # on the main menu, also show our news..
        class News(object):
            
            def __init__(self,activity):
                self._valid = True

                self._messageDuration = 10000
                self._messageSpacing = 2000
                self._text = None
                self._activity = weakref.ref(activity)

                # if we're signed in, fetch news immediately.. otherwise wait until we are signed in
                self._fetchTimer = bs.Timer(1000,bs.WeakCall(self._tryFetchingNews),repeat=True)
                self._tryFetchingNews()

            # we now want to wait until we're signed in before fetching news
            def _tryFetchingNews(self):
                if bsInternal._getAccountState() == 'SIGNED_IN':
                    self._fetchNews()
                    self._fetchTimer = None
                
            def _fetchNews(self):
                try: launchCount = bs.getConfig()['launchCount']
                except Exception: launchCount = None
                global gLastNewsFetchTime
                gLastNewsFetchTime = time.time()
                
                #bsUtils.serverGet('bsNews',{'v':'2','lc':launchCount,'b':bs.getEnvironment()['buildNumber'],'t':int(gLastNewsFetchTime-gStartTime)},bs.WeakCall(self._gotNews))
                env = bs.getEnvironment()
                bsInternal._newsQuery(args={'v':2,'lc':launchCount,'t':int(gLastNewsFetchTime-gStartTime),'p':env['platform'],'sp':env['subplatform']},callback=bs.WeakCall(self._gotNews))

            def _changePhrase(self):

                global gLastNewsFetchTime
                
                # if our news is way out of date, lets re-request it.. otherwise, rotate our phrase
                if time.time()-gLastNewsFetchTime > 600.0:
                    self._fetchNews()
                    self._text = None
                else:
                    if self._text is not None:
                        if len(self._phrases) == 0:
                            for p in self._usedPhrases:
                                self._phrases.insert(0,p)
                        val = self._phrases.pop()
                        if val == '__ACH__':
                            vr = bs.getEnvironment()['vrMode']
                            bsUtils.Text(bs.Lstr(resource='nextAchievementsText'),
                                         color=(1,1,1,1) if vr else (0.95,0.9,1,0.4),
                                         hostOnly=True,
                                         maxWidth=200,
                                         position=(-300, -35),
                                         hAlign='right',
                                         transition='fadeIn',
                                         scale=0.9 if vr else 0.7,
                                         flatness=1.0 if vr else 0.6,
                                         shadow=1.0 if vr else 0.5,
                                         hAttach="center",
                                         vAttach="top",
                                         transitionDelay=1000,
                                         transitionOutDelay=self._messageDuration).autoRetain()
                            import bsAchievement
                            achs = [a for a in bsAchievement.gAchievements if not a.isComplete()]
                            if len(achs) > 0:
                                a = achs.pop(random.randrange(min(4,len(achs))))
                                a.createDisplay(-180,-35,1000,outDelay=self._messageDuration,style='news')
                            if len(achs) > 0:
                                a = achs.pop(random.randrange(min(8,len(achs))))
                                a.createDisplay(180,-35,1250,outDelay=self._messageDuration,style='news')
                        else:
                            s = self._messageSpacing
                            keys = {s:0,s+1000:1.0,s+self._messageDuration-1000:1.0,s+self._messageDuration:0.0}
                            bs.animate(self._text.node,"opacity",dict([[k,v] for k,v in keys.items()]))
                            self._text.node.text = val

            def _gotNews(self,data):
                
                # run this stuff in the context of our activity since we need to make nodes and stuff..
                # we should fix the serverGet call so it 
                activity = self._activity()
                if activity is None or activity.isFinalized(): return
                with bs.Context(activity):
                
                    if data is None: return
                    news = str(data['news'])
                    #news = data['news']

                    # throw out a subtle notice if a new version is available
                    try:
                        env = bs.getEnvironment()
                        # on test builds, report newer test-build availability
                        if env['testBuild']:
                            if 'latestTestBuild' in data and 'latestTestVersion' in data and data['latestTestBuild'] > env['buildNumber']:
                                def foo():
                                    bs.screenMessage(bs.Lstr(resource='newTestBuildAvailableText',subs=[('${VERSION}',str(data['latestTestVersion'])),
                                                                                                        ('${BUILD}',str(data['latestTestBuild'])),
                                                                                                        ('${ADDRESS}','files.froemling.net')]),(0.7,1,0))
                                    bs.playSound(bs.getSound('ding'))
                                bs.gameTimer(2000,foo)

                        elif 'latestVersion' in data:
                            # strip off any 'b1' type stuff
                            rawVersion = env['version'].split('b')[0]
                            ourVersion = [int(n) for n in rawVersion.split('.')]
                            while len(ourVersion) < 3: ourVersion.append(0)
                            newestVersion = [int(n) for n in data['latestVersion'].split('.')]
                            while len(newestVersion) < 3: newestVersion.append(0)
                            if newestVersion > ourVersion:
                                def foo():
                                    bs.screenMessage(bs.Lstr(resource='newVersionAvailableText',subs=[('${VERSION}',data['latestVersion']),
                                                                                                      ('${APP_NAME}',bs.Lstr(resource='titleText'))]),(0.7,1,0))
                                    bs.playSound(bs.getSound('ding'))
                                bs.gameTimer(2000,foo)
                    except Exception,e:
                        print 'Exception comparing versions:',e

                    # our news data now starts with 'BSNews:' so we can filter out
                    # result that arent actually coming in from our server
                    # (such as wireless access point setup pages)
                    if not news.startswith("BSNews:"): return
                    news = news[7:]
                    # if news == '' or not self._valid: return
                    self._phrases = []
                    # show upcoming achievements in non-vr versions
                    # (currently too hard to read in vr)
                    self._usedPhrases = (['__ACH__'] if not bs.getEnvironment()['vrMode'] else []) + [s for s in news.split('<br>\r\n') if s != '']
                    self._phraseChangeTimer = bs.Timer(self._messageDuration+self._messageSpacing,bs.WeakCall(self._changePhrase),repeat=True)

                    sc = 1.2 if (bs.getEnvironment()['interfaceType'] == 'small' or bs.getEnvironment()['vrMode']) else 0.8

                    self._text = bs.NodeActor(bs.newNode('text',
                                                         attrs={'vAttach':'top',
                                                                'hAttach':'center',
                                                                'hAlign':'center',
                                                                'vrDepth':-20,
                                                                'shadow':1.0 if bs.getEnvironment()['vrMode'] else 0.4,
                                                                'flatness':0.8,
                                                                'vAlign':'top',
                                                                'color':(1,1,1,1) if bs.getEnvironment()['vrMode'] else (0.7,0.65,0.75,1.0),
                                                                'scale':sc,
                                                                'maxWidth':900.0/sc,
                                                                'position':(0,-10)}))
                    self._changePhrase()
    def onTransitionIn(self):
        import bsInternal
        bs.Activity.onTransitionIn(self)
        global gDidInitialTransition
        random.seed(123)
        self._logoNode = None
        self._customLogoTexName = None
        self._wordActors = []
        env = bs.getEnvironment()

        # FIXME - shouldn't be doing things conditionally based on whether
        # the host is vr mode or not (clients may not be or vice versa) -
        # any differences need to happen at the engine level
        # so everyone sees things in their own optimal way
        vrMode = bs.getEnvironment()['vrMode']

        if not bs.getEnvironment().get('toolbarTest', True):
            self.myName = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'bottom',
                        'hAlign':
                        'center',
                        'color': (1.0, 1.0, 1.0, 1.0) if vrMode else
                        (0.5, 0.6, 0.5, 0.6),
                        'flatness':
                        1.0,
                        'shadow':
                        1.0 if vrMode else 0.5,
                        'scale': (0.9 if
                                  (env['interfaceType'] == 'small' or vrMode)
                                  else 0.7),  # FIXME need a node attr for this
                        'position': (0, 10),
                        'vrDepth':
                        -10,
                        'text':
                        u'\xa9 2018 Eric Froemling'
                    }))

        # throw up some text that only clients can see so they know that the
        # host is navigating menus while they're just staring at an
        # empty-ish screen..
        self._hostIsNavigatingText = bs.NodeActor(
            bs.newNode('text',
                       attrs={
                           'text':
                           bs.Lstr(resource='hostIsNavigatingMenusText',
                                   subs=[
                                       ('${HOST}',
                                        bsInternal._getAccountDisplayString())
                                   ]),
                           'clientOnly':
                           True,
                           'position': (0, -200),
                           'flatness':
                           1.0,
                           'hAlign':
                           'center'
                       }))
        if not gDidInitialTransition and hasattr(self, 'myName'):
            bs.animate(self.myName.node, 'opacity', {2300: 0, 3000: 1.0})

        # TEMP - testing hindi text
        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'center',
                        'hAlign':
                        'left',
                        'color': (1, 1, 1, 1),
                        'shadow':
                        1.0,
                        'flatness':
                        0.0,
                        'scale':
                        1,
                        'position': (-500, -40),
                        'text':
                        ('\xe0\xa4\x9c\xe0\xa4\xbf\xe0\xa4\xb8 \xe0\xa4\xad'
                         '\xe0\xa5\x80 \xe0\xa4\x9a\xe0\xa5\x80\xe0\xa5\x9b '
                         '\xe0\xa4\x95\xe0\xa5\x8b \xe0\xa4\x9b\xe0\xa5\x81'
                         '\xe0\xa4\x8f\xe0\xa4\x81\xe0\xa4\x97\xe0\xa5\x87 '
                         '\xe0\xa4\x89\xe0\xa4\xb8\xe0\xa4\xb8\xe0\xa5\x87 '
                         '\xe0\xa4\x9a\xe0\xa4\xbf\xe0\xa4\xaa\xe0\xa4\x95'
                         '\n\xe0\xa4\x9c\xe0\xa4\xbe\xe0\xa4\xaf\xe0\xa5\x87'
                         '\xe0\xa4\x82\xe0\xa4\x97\xe0\xa5\x87 .. \xe0\xa4'
                         '\x87\xe0\xa4\xb8\xe0\xa4\x95\xe0\xa4\xbe \xe0\xa4'
                         '\xae\xe0\xa5\x9b\xe0\xa4\xbe \xe0\xa4\xb2\xe0\xa5'
                         '\x87\xe0\xa4\x82 !')
                    }))
        # TEMP - test emoji
        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'vAttach': 'center',
                               'hAlign': 'left',
                               'color': (1, 1, 1, 1),
                               'shadow': 1.0,
                               'flatness': 1.0,
                               'scale': 1,
                               'position': (-500, -40),
                               'text': ('TST: "deivit \xf0\x9f\x90\xa2"')
                           }))
        # TEMP - testing something; forgot what
        if False:
            # bs.screenMessage("TESTING: "+'TST: "deivit \xf0\x9f\x90\xa2"')
            self.tTest = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'center',
                        'hAlign':
                        'left',
                        'color': (1, 1, 1, 1),
                        'shadow':
                        1.0,
                        'flatness':
                        0.0,
                        'scale':
                        1,
                        'position': (-500, 0),
                        'text':
                        u('        \u3147\u3147                             '
                          '            \uad8c\ucc2c\uadfc                   '
                          '                        \uae40\uc6d0\uc7ac\n     '
                          '   \ub10c                                        '
                          '    \uc804\uac10\ud638\nlll\u0935\u093f\u0936\u0947'
                          '\u0937 \u0927\u0928\u094d\u092f\u0935\u093e'
                          '\u0926:\n')
                    }))
        self.tTest = bs.NodeActor(
            bs.newNode('text',
                       attrs={
                           'vAttach': 'center',
                           'hAlign': 'left',
                           'color': (0, 8, 0, 1),
                           'shadow': 1.0,
                           'flatness': 1.0,
                           'scale': 3,
                           'position': (0, -30),
                           'text': ('EVOLVED')
                       }))
        if False:
            self.tTest = bs.NodeActor(
                bs.newNode(
                    'text',
                    attrs={
                        'vAttach':
                        'center',
                        'hAlign':
                        'center',
                        'color': (1, 1, 1, 1),
                        'shadow':
                        1.0,
                        'flatness':
                        0.0,
                        'scale':
                        1,
                        'position': (-400, -40),
                        'text':
                        ('TST: "\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4'
                         '\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n\xe6\x88\x90\xe5'
                         '\xb0\xb1\xe4\xb8\xad|         foo\n\xe8\xb4\xa6'
                         '\xe6\x88\xb7 \xe7\x99\xbb\xe9\x99\x86foo\nend"'
                         '\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a'
                         '\xe5\x9b\xbe\xe6\xa0\x87"\nend"\xe8\x8e\xb7\xe5'
                         '\x8f\x96\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6'
                         '\xa0\x87"\nend2"\xe8\x8e\xb7\xe5\x8f\x96\xe6\x9b'
                         '\xb4\xe5\xa4\x9a\xe5\x9b\xbe\xe6\xa0\x87"\n')
                    }))

        # FIXME - shouldn't be doing things conditionally based on whether
        # the host is vr mode or not (clients may not be or vice versa)
        # - any differences need to happen at the engine level
        # so everyone sees things in their own optimal way
        vrMode = env['vrMode']
        interfaceType = env['interfaceType']

        # in cases where we're doing lots of dev work lets
        # always show the build number
        forceShowBuildNumber = False

        if not bs.getEnvironment().get('toolbarTest', True):
            if env['debugBuild'] or env['testBuild'] or forceShowBuildNumber:
                if env['debugBuild']:
                    text = bs.Lstr(value='${V} (${B}) (${D})',
                                   subs=[('${V}', env['version']),
                                         ('${B}', str(env['buildNumber'])),
                                         ('${D}',
                                          bs.Lstr(resource='debugText'))])
                else:
                    text = bs.Lstr(value='${V} (${B})',
                                   subs=[('${V}', env['version']),
                                         ('${B}', str(env['buildNumber']))])
            else:
                text = bs.Lstr(value='${V}', subs=[('${V}', env['version'])])
            self.version = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'vAttach':
                               'bottom',
                               'hAttach':
                               'right',
                               'hAlign':
                               'right',
                               'flatness':
                               1.0,
                               'vrDepth':
                               -10,
                               'shadow':
                               1.0 if vrMode else 0.5,
                               'color': (1, 1, 1, 1) if vrMode else
                               (0.5, 0.6, 0.5, 0.7),
                               'scale':
                               0.9 if
                               (interfaceType == 'small' or vrMode) else 0.7,
                               'position': (-260, 10) if vrMode else (-10, 10),
                               'text':
                               text
                           }))
            if not gDidInitialTransition:
                bs.animate(self.version.node, 'opacity', {2300: 0, 3000: 1.0})

        # throw in beta info..
        self.betaInfo = self.betaInfo2 = None
        if env['testBuild'] and not env['kioskMode']:
            self.betaInfo = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'vAttach':
                               'center',
                               'hAlign':
                               'center',
                               'color': (1, 1, 1, 1),
                               'shadow':
                               0.5,
                               'flatness':
                               0.5,
                               'scale':
                               1,
                               'vrDepth':
                               -60,
                               'position': (230, 125) if env['kioskMode'] else
                               (230, 35),
                               'text':
                               bs.Lstr(resource='testBuildText')
                           }))
            if not gDidInitialTransition:
                bs.animate(self.betaInfo.node, 'opacity', {1300: 0, 1800: 1.0})

        model = bs.getModel('bridgitLevelTop')
        treesModel = bs.getModel('trees')
        bottomModel = bs.getModel('bridgitLevelBottom')
        testColorTexture = bs.getTexture('bridgitLevelColor')
        treesTexture = bs.getTexture('bombColorIce')
        bgTex = bs.getTexture('natureBackgroundColor')
        bgModel = bs.getModel('natureBackground')
        bgCollide = bs.getCollideModel('natureBackgroundCollide')

        # (load these last since most platforms don't use them..)
        vrBottomFillModel = bs.getModel('thePadVRFillBottom')
        vrTopFillModel = bs.getModel('thePadVRFillTop')

        bsGlobals = bs.getSharedObject('globals')

        if False:
            node = bs.newNode('timeDisplay',
                              attrs={
                                  'timeMin': 2000,
                                  'timeMax': 10000,
                                  'showSubSeconds': True
                              })
            self._fooText = bs.NodeActor(
                bs.newNode('text',
                           attrs={
                               'position': (0, -220),
                               'flatness': 1.0,
                               'hAlign': 'center'
                           }))
            bsGlobals.connectAttr('gameTime', node, 'time2')
            node.connectAttr('output', self._fooText.node, 'text')

        tint = (1.14, 1.1, 1.0)
        bsGlobals.tint = tint

        bsGlobals.ambientColor = (1.06, 1.04, 1.03)
        bsGlobals.vignetteOuter = (0.45, 0.55, 0.54)
        bsGlobals.vignetteInner = (0.99, 0.98, 0.98)

        #self.bottom = bs.NodeActor(bs.newNode('terrain', attrs={
        #    'model':bottomModel,
        #    'lighting':False,
        #    'reflection':'soft',
        #    'reflectionScale':[0.45],
        #    'colorTexture':testColorTexture}))
        self.vrBottomFill = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': vrBottomFillModel,
                           'lighting': False,
                           'vrOnly': True,
                           'colorTexture': testColorTexture
                       }))
        self.vrTopFill = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': vrTopFillModel,
                           'vrOnly': True,
                           'lighting': False,
                           'colorTexture': bgTex
                       }))
        #self.terrain = bs.NodeActor(bs.newNode('terrain', attrs={
        #    'model':model,
        #    'colorTexture':testColorTexture,
        #    'reflection':'soft',
        #    'reflectionScale':[0.3]}))
        self.trees = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': treesModel,
                           'lighting': True,
                           'reflection': 'char',
                           'reflectionScale': [0.1],
                           'colorTexture': treesTexture
                       }))
        self.bg = bs.NodeActor(
            bs.newNode('terrain',
                       attrs={
                           'model': bgModel,
                           'color': (0.92, 0.91, 0.9),
                           'lighting': False,
                           'background': True,
                           'colorTexture': bgTex,
                           'collideModel': bgCollide,
                           'materials':
                           [bs.getSharedObject('footingMaterial')]
                       }))

        def _spawnBall():
            bs.Something(
                (10, random.randint(-2, 8), random.randint(-5, 5)),
                (-20, random.randint(-2, 2), 0),
                (True, int(((random.randint(1, 8) / 4) * 1000)))).autoRetain()

        self.timer = bs.Timer(1000, bs.Call(_spawnBall), repeat=True)
        textOffsetV = 0
        self._ts = 0.86

        self._language = None
        self._updateTimer = bs.Timer(1000, self._update, repeat=True)
        self._update()

        # hopefully this won't hitch but lets space these out anyway..
        bsInternal._addCleanFrameCallback(bs.WeakCall(self._startPreloads))

        random.seed()

        # on the main menu, also show our news..
        class News(object):
            def __init__(self, activity):
                self._valid = True
                self._messageDuration = 10000
                self._messageSpacing = 2000
                self._text = None
                self._activity = weakref.ref(activity)
                # if we're signed in, fetch news immediately..
                # otherwise wait until we are signed in
                self._fetchTimer = bs.Timer(1000,
                                            bs.WeakCall(self._tryFetchingNews),
                                            repeat=True)
                self._tryFetchingNews()

            # we now want to wait until we're signed in before fetching news
            def _tryFetchingNews(self):
                if bsInternal._getAccountState() == 'SIGNED_IN':
                    self._fetchNews()
                    self._fetchTimer = None

            def _fetchNews(self):
                try:
                    launchCount = bs.getConfig()['launchCount']
                except Exception:
                    launchCount = None
                global gLastNewsFetchTime
                gLastNewsFetchTime = time.time()

                # UPDATE - we now just pull news from MRVs
                news = bsInternal._getAccountMiscReadVal('n', None)
                if news is not None:
                    self._gotNews(news)

            def _changePhrase(self):

                global gLastNewsFetchTime

                # if our news is way out of date, lets re-request it..
                # otherwise, rotate our phrase
                if time.time() - gLastNewsFetchTime > 600.0:
                    self._fetchNews()
                    self._text = None
                else:
                    if self._text is not None:
                        if len(self._phrases) == 0:
                            for p in self._usedPhrases:
                                self._phrases.insert(0, p)
                        val = self._phrases.pop()
                        if val == '__ACH__':
                            vr = bs.getEnvironment()['vrMode']
                            bsUtils.Text(
                                bs.Lstr(resource='nextAchievementsText'),
                                color=(1,1,1,1) if vr else (0.95,0.9,1,0.4),
                                hostOnly=True,
                                maxWidth=200,
                                position=(-300, -35),
                                hAlign='right',
                                transition='fadeIn',
                                scale=0.9 if vr else 0.7,
                                flatness=1.0 if vr else 0.6,
                                shadow=1.0 if vr else 0.5,
                                hAttach="center",
                                vAttach="top",
                                transitionDelay=1000,
                                transitionOutDelay=self._messageDuration)\
                                   .autoRetain()
                            import bsAchievement
                            achs = [
                                a for a in bsAchievement.gAchievements
                                if not a.isComplete()
                            ]
                            if len(achs) > 0:
                                a = achs.pop(
                                    random.randrange(min(4, len(achs))))
                                a.createDisplay(-180,
                                                -35,
                                                1000,
                                                outDelay=self._messageDuration,
                                                style='news')
                            if len(achs) > 0:
                                a = achs.pop(
                                    random.randrange(min(8, len(achs))))
                                a.createDisplay(180,
                                                -35,
                                                1250,
                                                outDelay=self._messageDuration,
                                                style='news')
                        else:
                            s = self._messageSpacing
                            keys = {
                                s: 0,
                                s + 1000: 1.0,
                                s + self._messageDuration - 1000: 1.0,
                                s + self._messageDuration: 0.0
                            }
                            bs.animate(self._text.node, "opacity",
                                       dict([[k, v] for k, v in keys.items()]))
                            self._text.node.text = val

            def _gotNews(self, news):

                # run this stuff in the context of our activity since we need
                # to make nodes and stuff.. should fix the serverGet call so it
                activity = self._activity()
                if activity is None or activity.isFinalized(): return
                with bs.Context(activity):

                    self._phrases = []
                    # show upcoming achievements in non-vr versions
                    # (currently too hard to read in vr)
                    self._usedPhrases = (
                        ['__ACH__'] if not bs.getEnvironment()['vrMode'] else
                        []) + [s for s in news.split('<br>\n') if s != '']
                    self._phraseChangeTimer = bs.Timer(
                        self._messageDuration + self._messageSpacing,
                        bs.WeakCall(self._changePhrase),
                        repeat=True)

                    sc = 1.2 if (
                        bs.getEnvironment()['interfaceType'] == 'small'
                        or bs.getEnvironment()['vrMode']) else 0.8

                    self._text = bs.NodeActor(
                        bs.newNode(
                            'text',
                            attrs={
                                'vAttach':
                                'top',
                                'hAttach':
                                'center',
                                'hAlign':
                                'center',
                                'vrDepth':
                                -20,
                                'shadow':
                                1.0 if bs.getEnvironment()['vrMode'] else 0.4,
                                'flatness':
                                0.8,
                                'vAlign':
                                'top',
                                'color':
                                ((1, 1, 1,
                                  1) if bs.getEnvironment()['vrMode'] else
                                 (0.7, 0.65, 0.75, 1.0)),
                                'scale':
                                sc,
                                'maxWidth':
                                900.0 / sc,
                                'position': (0, -10)
                            }))
                    self._changePhrase()

        if not env['kioskMode'] and not env.get('toolbarTest', True):
            self._news = News(self)

        # bring up the last place we were, or start at the main menu otherwise
        with bs.Context('UI'):
            try:
                mainWindow = bsUI.gMainWindow
            except Exception:
                mainWindow = None

            # when coming back from a kiosk-mode game, jump to
            # the kiosk start screen.. if bsUtils.gRunningKioskModeGame:
            if bs.getEnvironment()['kioskMode']:
                bsUI.uiGlobals['mainMenuWindow'] = \
                     bsUI.KioskWindow().getRootWidget()
            # ..or in normal cases go back to the main menu
            else:
                if mainWindow == 'Gather':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.GatherWindow(transition=None).getRootWidget()
                elif mainWindow == 'Watch':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.WatchWindow(transition=None).getRootWidget()
                elif mainWindow == 'Team Game Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.TeamsWindow(sessionType=bs.TeamsSession,
                                         transition=None).getRootWidget()
                elif mainWindow == 'Free-for-All Game Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.TeamsWindow(sessionType=bs.FreeForAllSession,
                                         transition=None).getRootWidget()
                elif mainWindow == 'Coop Select':
                    bsUI.uiGlobals['mainMenuWindow'] = \
                        bsUI.CoopWindow(transition=None).getRootWidget()
                else:                    bsUI.uiGlobals['mainMenuWindow'] = \
                  bsUI.MainMenuWindow(transition=None).getRootWidget()

                # attempt to show any pending offers immediately.
                # If that doesn't work, try again in a few seconds
                # (we may not have heard back from the server)
                # ..if that doesn't work they'll just have to wait
                # until the next opportunity.
                if not bsUI._showOffer():

                    def tryAgain():
                        if not bsUI._showOffer():
                            # try one last time..
                            bs.realTimer(2000, bsUI._showOffer)

                    bs.realTimer(2000, tryAgain)

        gDidInitialTransition = True