def get_award_ticket_value(self, include_pro_bonus: bool = False) -> int:
     """Get the ticket award value for this achievement."""
     val: int = (_ba.get_v1_account_misc_read_val('achAward.' + self._name,
                                                  self._award) *
                 _get_ach_mult(include_pro_bonus))
     assert isinstance(val, int)
     return val
Beispiel #2
0
    def _new_profile(self) -> None:
        # pylint: disable=cyclic-import
        from bastd.ui.profile.edit import EditProfileWindow
        from bastd.ui.purchase import PurchaseWindow

        # Limit to a handful profiles if they don't have pro-options.
        max_non_pro_profiles = _ba.get_v1_account_misc_read_val('mnpp', 5)
        assert self._profiles is not None
        if (not ba.app.accounts_v1.have_pro_options()
                and len(self._profiles) >= max_non_pro_profiles):
            PurchaseWindow(items=['pro'],
                           header_text=ba.Lstr(
                               resource='unlockThisProfilesText',
                               subs=[('${NUM}', str(max_non_pro_profiles))]))
            return

        # Clamp at 100 profiles (otherwise the server will and that's less
        # elegant looking).
        if len(self._profiles) > 100:
            ba.screenmessage(
                ba.Lstr(translate=('serverResponses',
                                   'Max number of profiles reached.')),
                color=(1, 0, 0))
            ba.playsound(ba.getsound('error'))
            return

        self._save_state()
        ba.containerwidget(edit=self._root_widget, transition='out_left')
        ba.app.ui.set_main_menu_window(
            EditProfileWindow(
                existing_profile=None,
                in_main_menu=self._in_main_menu).get_root_widget())
Beispiel #3
0
            def _fetch_news(self) -> None:
                ba.app.main_menu_last_news_fetch_time = time.time()

                # UPDATE - We now just pull news from MRVs.
                news = _ba.get_v1_account_misc_read_val('n', None)
                if news is not None:
                    self._got_news(news)
Beispiel #4
0
    def _update(self) -> None:

        # If they want us to close once we're signed in, do so.
        if self._close_once_signed_in and self._signed_in:
            self._back()
            return

        # Hmm should update this to use get_account_state_num.
        # Theoretically if we switch from one signed-in account to another
        # in the background this would break.
        account_state_num = _ba.get_v1_account_state_num()
        account_state = _ba.get_v1_account_state()

        show_linked = (self._signed_in and _ba.get_v1_account_misc_read_val(
            'allowAccountLinking2', False))

        if (account_state_num != self._account_state_num
                or self._show_linked != show_linked or self._needs_refresh):
            self._show_linked = show_linked
            self._account_state_num = account_state_num
            self._signed_in = (account_state == 'signed_in')
            self._refresh()

        # Go ahead and refresh some individual things
        # that may change under us.
        self._update_linked_accounts_text()
        self._update_unlink_accounts_button()
        self._refresh_campaign_progress_text()
        self._refresh_achievements()
        self._refresh_tickets_text()
        self._refresh_account_name_text()
def _get_ach_mult(include_pro_bonus: bool = False) -> int:
    """Return the multiplier for achievement pts.

    (just for display; changing this here won't affect actual rewards)
    """
    val: int = _ba.get_v1_account_misc_read_val('achAwardMult', 5)
    assert isinstance(val, int)
    if include_pro_bonus and _ba.app.accounts_v1.have_pro():
        val *= 2
    return val
Beispiel #6
0
def _calc_count_for_tab(tabval: list[dict[str, Any]], our_tickets: int,
                        count: int) -> int:
    for section in tabval:
        for item in section['items']:
            ticket_cost = _ba.get_v1_account_misc_read_val(
                'price.' + item, None)
            if ticket_cost is not None:
                if (our_tickets >= ticket_cost
                        and not _ba.get_purchased(item)):
                    count += 1
    return count
Beispiel #7
0
    def buy(self, item: str) -> None:
        """Attempt to purchase the provided item."""
        from ba.internal import (get_available_sale_time,
                                 get_store_item_name_translated)
        from bastd.ui import account
        from bastd.ui.confirm import ConfirmWindow
        from bastd.ui import getcurrency

        # Prevent pressing buy within a few seconds of the last press
        # (gives the buttons time to disable themselves and whatnot).
        curtime = ba.time(ba.TimeType.REAL)
        if self._last_buy_time is not None and (curtime -
                                                self._last_buy_time) < 2.0:
            ba.playsound(ba.getsound('error'))
        else:
            if _ba.get_v1_account_state() != 'signed_in':
                account.show_sign_in_prompt()
            else:
                self._last_buy_time = curtime

                # Pro is an actual IAP; the rest are ticket purchases.
                if item == 'pro':
                    ba.playsound(ba.getsound('click01'))

                    # Purchase either pro or pro_sale depending on whether
                    # there is a sale going on.
                    self._do_purchase_check('pro' if get_available_sale_time(
                        'extras') is None else 'pro_sale')
                else:
                    price = _ba.get_v1_account_misc_read_val(
                        'price.' + item, None)
                    our_tickets = _ba.get_v1_account_ticket_count()
                    if price is not None and our_tickets < price:
                        ba.playsound(ba.getsound('error'))
                        getcurrency.show_get_tickets_prompt()
                    else:

                        def do_it() -> None:
                            self._do_purchase_check(item,
                                                    is_ticket_purchase=True)

                        ba.playsound(ba.getsound('swish'))
                        ConfirmWindow(
                            ba.Lstr(resource='store.purchaseConfirmText',
                                    subs=[
                                        ('${ITEM}',
                                         get_store_item_name_translated(item))
                                    ]),
                            width=400,
                            height=120,
                            action=do_it,
                            ok_text=ba.Lstr(resource='store.purchaseText',
                                            fallback_resource='okText'))
Beispiel #8
0
 def _on_activity_mult_press(self) -> None:
     from bastd.ui import confirm
     txt = ba.Lstr(
         resource='coopSelectWindow.activenessAllTimeInfoText'
         if self._season == 'a' else 'coopSelectWindow.activenessInfoText',
         subs=[('${MAX}',
                str(_ba.get_v1_account_misc_read_val('activenessMax',
                                                     1.0)))])
     confirm.ConfirmWindow(txt,
                           cancel_button=False,
                           width=460,
                           height=150,
                           origin_widget=self._activity_mult_button)
Beispiel #9
0
    def __init__(self, settings: dict):
        """Instantiate the Activity."""
        super().__init__(settings)

        # Holds some flattened info about the player set at the point
        # when on_begin() is called.
        self.initialplayerinfos: Optional[list[ba.PlayerInfo]] = None

        # Go ahead and get our map loading.
        self._map_type = _map.get_map_class(self._calc_map_name(settings))

        self._spawn_sound = _ba.getsound('spawn')
        self._map_type.preload()
        self._map: Optional[ba.Map] = None
        self._powerup_drop_timer: Optional[ba.Timer] = None
        self._tnt_spawners: Optional[dict[int, TNTSpawner]] = None
        self._tnt_drop_timer: Optional[ba.Timer] = None
        self._game_scoreboard_name_text: Optional[ba.Actor] = None
        self._game_scoreboard_description_text: Optional[ba.Actor] = None
        self._standard_time_limit_time: Optional[int] = None
        self._standard_time_limit_timer: Optional[ba.Timer] = None
        self._standard_time_limit_text: Optional[ba.NodeActor] = None
        self._standard_time_limit_text_input: Optional[ba.NodeActor] = None
        self._tournament_time_limit: Optional[int] = None
        self._tournament_time_limit_timer: Optional[ba.Timer] = None
        self._tournament_time_limit_title_text: Optional[ba.NodeActor] = None
        self._tournament_time_limit_text: Optional[ba.NodeActor] = None
        self._tournament_time_limit_text_input: Optional[ba.NodeActor] = None
        self._zoom_message_times: dict[int, float] = {}
        self._is_waiting_for_continue = False

        self._continue_cost = _ba.get_v1_account_misc_read_val(
            'continueStartCost', 25)
        self._continue_cost_mult = _ba.get_v1_account_misc_read_val(
            'continuesMult', 2)
        self._continue_cost_offset = _ba.get_v1_account_misc_read_val(
            'continuesOffset', 0)
Beispiel #10
0
 def _on_pro_mult_press(self) -> None:
     from bastd.ui import confirm
     txt = ba.Lstr(resource='coopSelectWindow.proMultInfoText',
                   subs=[('${PERCENT}',
                          str(
                              _ba.get_v1_account_misc_read_val(
                                  'proPowerRankingBoost', 10))),
                         ('${PRO}',
                          ba.Lstr(resource='store.bombSquadProNameText',
                                  subs=[('${APP_NAME}',
                                         ba.Lstr(resource='titleText'))]))])
     confirm.ConfirmWindow(txt,
                           cancel_button=False,
                           width=460,
                           height=130,
                           origin_widget=self._pro_mult_button)
Beispiel #11
0
    def update(self) -> None:
        """Update!"""
        if not self._root_widget:
            return

        # Update boost-price.
        if self._boost_price is not None:
            ba.textwidget(edit=self._boost_price,
                          text=ba.charstr(ba.SpecialChar.TICKET) +
                          str(self._boost_tickets))

        # Update boost button color based on if we have enough moola.
        if self._boost_button is not None:
            can_boost = (
                (_ba.get_v1_account_state() == 'signed_in'
                 and _ba.get_v1_account_ticket_count() >= self._boost_tickets))
            ba.buttonwidget(edit=self._boost_button,
                            color=(0, 1, 0) if can_boost else (0.7, 0.7, 0.7))

        # Update ticket-count.
        if self._tickets_text is not None:
            if self._boost_button is not None:
                if _ba.get_v1_account_state() == 'signed_in':
                    val = ba.charstr(ba.SpecialChar.TICKET) + str(
                        _ba.get_v1_account_ticket_count())
                else:
                    val = ba.charstr(ba.SpecialChar.TICKET) + '???'
                ba.textwidget(edit=self._tickets_text, text=val)
            else:
                ba.textwidget(edit=self._tickets_text, text='')

        current_time = ba.time(ba.TimeType.REAL)
        if (self._last_transaction_time is None
                or current_time - self._last_transaction_time >
                0.001 * _ba.get_v1_account_misc_read_val('pqInt', 5000)):
            self._last_transaction_time = current_time
            _ba.add_transaction(
                {
                    'type': 'PARTY_QUEUE_QUERY',
                    'q': self._queue_id
                },
                callback=ba.WeakCall(self.on_update_response))
            _ba.run_transactions()

        # step our dudes
        for dude in self._dudes:
            dude.step(self._smoothing)
Beispiel #12
0
 def _purchase_check_result(self, item: str, is_ticket_purchase: bool,
                            result: Optional[dict[str, Any]]) -> None:
     if result is None:
         ba.playsound(ba.getsound('error'))
         ba.screenmessage(
             ba.Lstr(resource='internal.unavailableNoConnectionText'),
             color=(1, 0, 0))
     else:
         if is_ticket_purchase:
             if result['allow']:
                 price = _ba.get_v1_account_misc_read_val(
                     'price.' + item, None)
                 if (price is None or not isinstance(price, int)
                         or price <= 0):
                     print('Error; got invalid local price of', price,
                           'for item', item)
                     ba.playsound(ba.getsound('error'))
                 else:
                     ba.playsound(ba.getsound('click01'))
                     _ba.in_game_purchase(item, price)
             else:
                 if result['reason'] == 'versionTooOld':
                     ba.playsound(ba.getsound('error'))
                     ba.screenmessage(ba.Lstr(
                         resource='getTicketsWindow.versionTooOldText'),
                                      color=(1, 0, 0))
                 else:
                     ba.playsound(ba.getsound('error'))
                     ba.screenmessage(ba.Lstr(
                         resource='getTicketsWindow.unavailableText'),
                                      color=(1, 0, 0))
         # Real in-app purchase.
         else:
             if result['allow']:
                 _ba.purchase(item)
             else:
                 if result['reason'] == 'versionTooOld':
                     ba.playsound(ba.getsound('error'))
                     ba.screenmessage(ba.Lstr(
                         resource='getTicketsWindow.versionTooOldText'),
                                      color=(1, 0, 0))
                 else:
                     ba.playsound(ba.getsound('error'))
                     ba.screenmessage(ba.Lstr(
                         resource='getTicketsWindow.unavailableText'),
                                      color=(1, 0, 0))
Beispiel #13
0
    def continue_or_end_game(self) -> None:
        """If continues are allowed, prompts the player to purchase a continue
        and calls either end_game or continue_game depending on the result"""
        # pylint: disable=too-many-nested-blocks
        # pylint: disable=cyclic-import
        from bastd.ui.continues import ContinuesWindow
        from ba._coopsession import CoopSession
        from ba._generated.enums import TimeType

        try:
            if _ba.get_v1_account_misc_read_val('enableContinues', False):
                session = self.session

                # We only support continuing in non-tournament games.
                tournament_id = session.tournament_id
                if tournament_id is None:

                    # We currently only support continuing in sequential
                    # co-op campaigns.
                    if isinstance(session, CoopSession):
                        assert session.campaign is not None
                        if session.campaign.sequential:
                            gnode = self.globalsnode

                            # Only attempt this if we're not currently paused
                            # and there appears to be no UI.
                            if (not gnode.paused
                                    and not _ba.app.ui.has_main_menu_window()):
                                self._is_waiting_for_continue = True
                                with _ba.Context('ui'):
                                    _ba.timer(
                                        0.5,
                                        lambda: ContinuesWindow(
                                            self,
                                            self._continue_cost,
                                            continue_call=WeakCall(
                                                self._continue_choice, True),
                                            cancel_call=WeakCall(
                                                self._continue_choice, False)),
                                        timetype=TimeType.REAL)
                                return

        except Exception:
            print_exception('Error handling continues.')

        self.end_game()
Beispiel #14
0
    def _disabled_press(self) -> None:

        # if we're on a platform without purchases, inform the user they
        # can link their accounts and buy stuff elsewhere
        app = ba.app
        if ((app.test_build or
             (app.platform == 'android'
              and app.subplatform in ['oculus', 'cardboard']))
                and _ba.get_v1_account_misc_read_val('allowAccountLinking2',
                                                     False)):
            ba.screenmessage(ba.Lstr(resource=self._r +
                                     '.unavailableLinkAccountText'),
                             color=(1, 0.5, 0))
        else:
            ba.screenmessage(ba.Lstr(resource=self._r + '.unavailableText'),
                             color=(1, 0.5, 0))
        ba.playsound(ba.getsound('error'))
Beispiel #15
0
    def get_league_rank_points(self,
                               data: Optional[dict[str, Any]],
                               subset: str = None) -> int:
        """(internal)"""
        if data is None:
            return 0

        # If the data contains an achievement total, use that. otherwise calc
        # locally.
        if data['at'] is not None:
            total_ach_value = data['at']
        else:
            total_ach_value = 0
            for ach in _ba.app.ach.achievements:
                if ach.complete:
                    total_ach_value += ach.power_ranking_value

        trophies_total: int = (data['t0a'] * data['t0am'] +
                               data['t0b'] * data['t0bm'] +
                               data['t1'] * data['t1m'] +
                               data['t2'] * data['t2m'] +
                               data['t3'] * data['t3m'] +
                               data['t4'] * data['t4m'])
        if subset == 'trophyCount':
            val: int = (data['t0a'] + data['t0b'] + data['t1'] + data['t2'] +
                        data['t3'] + data['t4'])
            assert isinstance(val, int)
            return val
        if subset == 'trophies':
            assert isinstance(trophies_total, int)
            return trophies_total
        if subset is not None:
            raise ValueError('invalid subset value: ' + str(subset))

        if data['p']:
            pro_mult = 1.0 + float(
                _ba.get_v1_account_misc_read_val('proPowerRankingBoost',
                                                 0.0)) * 0.01
        else:
            pro_mult = 1.0

        # For final value, apply our pro mult and activeness-mult.
        return int(
            (total_ach_value + trophies_total) *
            (data['act'] if data['act'] is not None else 1.0) * pro_mult)
Beispiel #16
0
    def _query_party_list_periodically(self) -> None:
        now = ba.time(ba.TimeType.REAL)

        # Fire off a new public-party query periodically.
        if (self._last_server_list_query_time is None
                or now - self._last_server_list_query_time > 0.001 *
                _ba.get_v1_account_misc_read_val('pubPartyRefreshMS', 10000)):
            self._last_server_list_query_time = now
            if DEBUG_SERVER_COMMUNICATION:
                print('REQUESTING SERVER LIST')
            if _ba.get_v1_account_state() == 'signed_in':
                _ba.add_transaction(
                    {
                        'type': 'PUBLIC_PARTY_QUERY',
                        'proto': ba.app.protocol_version,
                        'lang': ba.app.lang.language
                    },
                    callback=ba.WeakCall(self._on_public_party_query_result))
                _ba.run_transactions()
            else:
                self._on_public_party_query_result(None)
Beispiel #17
0
    def __init__(self,
                 transition: str = 'in_right',
                 from_modal_store: bool = False,
                 modal: bool = False,
                 origin_widget: ba.Widget = None,
                 store_back_location: str = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals

        ba.set_analytics_screen('Get Tickets Window')

        self._transitioning_out = False
        self._store_back_location = store_back_location  # ew.

        self._ad_button_greyed = False
        self._smooth_update_timer: Optional[ba.Timer] = None
        self._ad_button = None
        self._ad_label = None
        self._ad_image = None
        self._ad_time_text = None

        # If they provided an origin-widget, scale up from that.
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        uiscale = ba.app.ui.uiscale
        self._width = 1000.0 if uiscale is ba.UIScale.SMALL else 800.0
        x_inset = 100.0 if uiscale is ba.UIScale.SMALL else 0.0
        self._height = 480.0

        self._modal = modal
        self._from_modal_store = from_modal_store
        self._r = 'getTicketsWindow'

        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            color=(0.4, 0.37, 0.55),
            scale=(1.63 if uiscale is ba.UIScale.SMALL else
                   1.2 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -3) if uiscale is ba.UIScale.SMALL else (0, 0)))

        btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(55 + x_inset, self._height - 79),
            size=(140, 60),
            scale=1.0,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if modal else 'backText'),
            button_type='regular' if modal else 'back',
            on_activate_call=self._back)

        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 55),
                      size=(0, 0),
                      color=ba.app.ui.title_color,
                      scale=1.2,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      maxwidth=290)

        if not modal:
            ba.buttonwidget(edit=btn,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))

        b_size = (220.0, 180.0)
        v = self._height - b_size[1] - 80
        spacing = 1

        self._ad_button = None

        def _add_button(item: str,
                        position: tuple[float, float],
                        size: tuple[float, float],
                        label: ba.Lstr,
                        price: str = None,
                        tex_name: str = None,
                        tex_opacity: float = 1.0,
                        tex_scale: float = 1.0,
                        enabled: bool = True,
                        text_scale: float = 1.0) -> ba.Widget:
            btn2 = ba.buttonwidget(
                parent=self._root_widget,
                position=position,
                button_type='square',
                size=size,
                label='',
                autoselect=True,
                color=None if enabled else (0.5, 0.5, 0.5),
                on_activate_call=(ba.Call(self._purchase, item)
                                  if enabled else self._disabled_press))
            txt = ba.textwidget(parent=self._root_widget,
                                text=label,
                                position=(position[0] + size[0] * 0.5,
                                          position[1] + size[1] * 0.3),
                                scale=text_scale,
                                maxwidth=size[0] * 0.75,
                                size=(0, 0),
                                h_align='center',
                                v_align='center',
                                draw_controller=btn2,
                                color=(0.7, 0.9, 0.7, 1.0 if enabled else 0.2))
            if price is not None and enabled:
                ba.textwidget(parent=self._root_widget,
                              text=price,
                              position=(position[0] + size[0] * 0.5,
                                        position[1] + size[1] * 0.17),
                              scale=0.7,
                              maxwidth=size[0] * 0.75,
                              size=(0, 0),
                              h_align='center',
                              v_align='center',
                              draw_controller=btn2,
                              color=(0.4, 0.9, 0.4, 1.0))
            i = None
            if tex_name is not None:
                tex_size = 90.0 * tex_scale
                i = ba.imagewidget(
                    parent=self._root_widget,
                    texture=ba.gettexture(tex_name),
                    position=(position[0] + size[0] * 0.5 - tex_size * 0.5,
                              position[1] + size[1] * 0.66 - tex_size * 0.5),
                    size=(tex_size, tex_size),
                    draw_controller=btn2,
                    opacity=tex_opacity * (1.0 if enabled else 0.25))
            if item == 'ad':
                self._ad_button = btn2
                self._ad_label = txt
                assert i is not None
                self._ad_image = i
                self._ad_time_text = ba.textwidget(
                    parent=self._root_widget,
                    text='1m 10s',
                    position=(position[0] + size[0] * 0.5,
                              position[1] + size[1] * 0.5),
                    scale=text_scale * 1.2,
                    maxwidth=size[0] * 0.85,
                    size=(0, 0),
                    h_align='center',
                    v_align='center',
                    draw_controller=btn2,
                    color=(0.4, 0.9, 0.4, 1.0))
            return btn2

        rsrc = self._r + '.ticketsText'

        c2txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_v1_account_misc_read_val('tickets2Amount',
                                                        500)))])
        c3txt = ba.Lstr(
            resource=rsrc,
            subs=[
                ('${COUNT}',
                 str(_ba.get_v1_account_misc_read_val('tickets3Amount', 1500)))
            ])
        c4txt = ba.Lstr(
            resource=rsrc,
            subs=[
                ('${COUNT}',
                 str(_ba.get_v1_account_misc_read_val('tickets4Amount', 5000)))
            ])
        c5txt = ba.Lstr(
            resource=rsrc,
            subs=[
                ('${COUNT}',
                 str(_ba.get_v1_account_misc_read_val('tickets5Amount',
                                                      15000)))
            ])

        h = 110.0

        # enable buttons if we have prices..
        tickets2_price = _ba.get_price('tickets2')
        tickets3_price = _ba.get_price('tickets3')
        tickets4_price = _ba.get_price('tickets4')
        tickets5_price = _ba.get_price('tickets5')

        # TEMP
        # tickets1_price = '$0.99'
        # tickets2_price = '$4.99'
        # tickets3_price = '$9.99'
        # tickets4_price = '$19.99'
        # tickets5_price = '$49.99'

        _add_button('tickets2',
                    enabled=(tickets2_price is not None),
                    position=(self._width * 0.5 - spacing * 1.5 -
                              b_size[0] * 2.0 + h, v),
                    size=b_size,
                    label=c2txt,
                    price=tickets2_price,
                    tex_name='ticketsMore')  # 0.99-ish
        _add_button('tickets3',
                    enabled=(tickets3_price is not None),
                    position=(self._width * 0.5 - spacing * 0.5 -
                              b_size[0] * 1.0 + h, v),
                    size=b_size,
                    label=c3txt,
                    price=tickets3_price,
                    tex_name='ticketRoll')  # 4.99-ish
        v -= b_size[1] - 5
        _add_button('tickets4',
                    enabled=(tickets4_price is not None),
                    position=(self._width * 0.5 - spacing * 1.5 -
                              b_size[0] * 2.0 + h, v),
                    size=b_size,
                    label=c4txt,
                    price=tickets4_price,
                    tex_name='ticketRollBig',
                    tex_scale=1.2)  # 9.99-ish
        _add_button('tickets5',
                    enabled=(tickets5_price is not None),
                    position=(self._width * 0.5 - spacing * 0.5 -
                              b_size[0] * 1.0 + h, v),
                    size=b_size,
                    label=c5txt,
                    price=tickets5_price,
                    tex_name='ticketRolls',
                    tex_scale=1.2)  # 19.99-ish

        self._enable_ad_button = _ba.has_video_ads()
        h = self._width * 0.5 + 110.0
        v = self._height - b_size[1] - 115.0

        if self._enable_ad_button:
            h_offs = 35
            b_size_3 = (150, 120)
            cdb = _add_button(
                'ad',
                position=(h + h_offs, v),
                size=b_size_3,
                label=ba.Lstr(resource=self._r + '.ticketsFromASponsorText',
                              subs=[('${COUNT}',
                                     str(
                                         _ba.get_v1_account_misc_read_val(
                                             'sponsorTickets', 5)))]),
                tex_name='ticketsMore',
                enabled=self._enable_ad_button,
                tex_opacity=0.6,
                tex_scale=0.7,
                text_scale=0.7)
            ba.buttonwidget(edit=cdb,
                            color=(0.65, 0.5,
                                   0.7) if self._enable_ad_button else
                            (0.5, 0.5, 0.5))

            self._ad_free_text = ba.textwidget(
                parent=self._root_widget,
                text=ba.Lstr(resource=self._r + '.freeText'),
                position=(h + h_offs + b_size_3[0] * 0.5,
                          v + b_size_3[1] * 0.5 + 25),
                size=(0, 0),
                color=(1, 1, 0, 1.0) if self._enable_ad_button else
                (1, 1, 1, 0.2),
                draw_controller=cdb,
                rotate=15,
                shadow=1.0,
                maxwidth=150,
                h_align='center',
                v_align='center',
                scale=1.0)
            v -= 125
        else:
            v -= 20

        if True:  # pylint: disable=using-constant-test
            h_offs = 35
            b_size_3 = (150, 120)
            cdb = _add_button(
                'app_invite',
                position=(h + h_offs, v),
                size=b_size_3,
                label=ba.Lstr(
                    resource='gatherWindow.earnTicketsForRecommendingText',
                    subs=[('${COUNT}',
                           str(
                               _ba.get_v1_account_misc_read_val(
                                   'sponsorTickets', 5)))]),
                tex_name='ticketsMore',
                enabled=True,
                tex_opacity=0.6,
                tex_scale=0.7,
                text_scale=0.7)
            ba.buttonwidget(edit=cdb, color=(0.65, 0.5, 0.7))

            ba.textwidget(parent=self._root_widget,
                          text=ba.Lstr(resource=self._r + '.freeText'),
                          position=(h + h_offs + b_size_3[0] * 0.5,
                                    v + b_size_3[1] * 0.5 + 25),
                          size=(0, 0),
                          color=(1, 1, 0, 1.0),
                          draw_controller=cdb,
                          rotate=15,
                          shadow=1.0,
                          maxwidth=150,
                          h_align='center',
                          v_align='center',
                          scale=1.0)
            tc_y_offs = 0

        h = self._width - (185 + x_inset)
        v = self._height - 95 + tc_y_offs

        txt1 = (ba.Lstr(
            resource=self._r +
            '.youHaveText').evaluate().partition('${COUNT}')[0].strip())
        txt2 = (ba.Lstr(
            resource=self._r +
            '.youHaveText').evaluate().rpartition('${COUNT}')[0].strip())

        ba.textwidget(parent=self._root_widget,
                      text=txt1,
                      position=(h, v),
                      size=(0, 0),
                      color=(0.5, 0.5, 0.6),
                      maxwidth=200,
                      h_align='center',
                      v_align='center',
                      scale=0.8)
        v -= 30
        self._ticket_count_text = ba.textwidget(parent=self._root_widget,
                                                position=(h, v),
                                                size=(0, 0),
                                                color=(0.2, 1.0, 0.2),
                                                maxwidth=200,
                                                h_align='center',
                                                v_align='center',
                                                scale=1.6)
        v -= 30
        ba.textwidget(parent=self._root_widget,
                      text=txt2,
                      position=(h, v),
                      size=(0, 0),
                      color=(0.5, 0.5, 0.6),
                      maxwidth=200,
                      h_align='center',
                      v_align='center',
                      scale=0.8)

        # update count now and once per second going forward..
        self._ticking_node: Optional[ba.Node] = None
        self._smooth_ticket_count: Optional[float] = None
        self._ticket_count = 0
        self._update()
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._smooth_increase_speed = 1.0
Beispiel #18
0
    def _update(self) -> None:
        # We may outlive our widgets.
        if not self.root_widget:
            return

        # If we've been foregrounded/backgrounded we need to re-grab data.
        if self._fg_state != ba.app.fg_state:
            self._fg_state = ba.app.fg_state
            self._have_valid_data = False

        # If we need to run another tournament query, do so.
        if not self._running_query and (
            (self._last_query_time is None) or (not self._have_valid_data) or
            (ba.time(ba.TimeType.REAL) - self._last_query_time > 30.0)):
            _ba.tournament_query(args={
                'source':
                    'entry window' if self._tournament_activity is None else
                    'retry entry window'
            },
                                 callback=ba.WeakCall(
                                     self._on_tournament_query_response))
            self._last_query_time = ba.time(ba.TimeType.REAL)
            self._running_query = True

        # Grab the latest info on our tourney.
        self._tournament_info = ba.app.accounts_v1.tournament_info[
            self._tournament_id]

        # If we don't have valid data always show a '-' for time.
        if not self._have_valid_data:
            ba.textwidget(edit=self._time_remaining_text, text='-')
        else:
            if self._seconds_remaining is not None:
                self._seconds_remaining = max(0, self._seconds_remaining - 1)
                ba.textwidget(edit=self._time_remaining_text,
                              text=ba.timestring(
                                  self._seconds_remaining * 1000,
                                  centi=False,
                                  timeformat=ba.TimeFormat.MILLISECONDS))

        # Keep price up-to-date and update the button with it.
        self._purchase_price = _ba.get_v1_account_misc_read_val(
            self._purchase_price_name, None)

        ba.textwidget(
            edit=self._ticket_cost_text,
            text=(ba.Lstr(resource='getTicketsWindow.freeText')
                  if self._purchase_price == 0 else ba.Lstr(
                      resource='getTicketsWindow.ticketsText',
                      subs=[('${COUNT}', str(self._purchase_price)
                             if self._purchase_price is not None else '?')])),
            position=self._ticket_cost_text_position_free
            if self._purchase_price == 0 else self._ticket_cost_text_position,
            scale=1.0 if self._purchase_price == 0 else 0.6)

        ba.textwidget(
            edit=self._free_plays_remaining_text,
            text='' if
            (self._tournament_info['freeTriesRemaining'] in [None, 0]
             or self._purchase_price != 0) else '' +
            str(self._tournament_info['freeTriesRemaining']))

        ba.imagewidget(edit=self._ticket_img,
                       opacity=0.2 if self._purchase_price == 0 else 1.0,
                       position=self._ticket_img_pos_free
                       if self._purchase_price == 0 else self._ticket_img_pos)

        if self._do_ad_btn:
            enabled = _ba.have_incentivized_ad()
            have_ad_tries_remaining = (
                self._tournament_info['adTriesRemaining'] is not None
                and self._tournament_info['adTriesRemaining'] > 0)
            ba.textwidget(edit=self._ad_text,
                          position=self._ad_text_position_remaining if
                          have_ad_tries_remaining else self._ad_text_position,
                          color=(0, 1, 0) if enabled else (0.5, 0.5, 0.5))
            ba.imagewidget(edit=self._pay_with_ad_img,
                           opacity=1.0 if enabled else 0.2)
            ba.buttonwidget(edit=self._pay_with_ad_btn,
                            color=(0.5, 0.7, 0.2) if enabled else
                            (0.5, 0.5, 0.5))
            ad_plays_remaining_text = (
                '' if not have_ad_tries_remaining else '' +
                str(self._tournament_info['adTriesRemaining']))
            ba.textwidget(edit=self._ad_plays_remaining_text,
                          text=ad_plays_remaining_text,
                          color=(0, 0.8, 0) if enabled else (0.4, 0.4, 0.4))

        try:
            t_str = str(_ba.get_v1_account_ticket_count())
        except Exception:
            t_str = '?'
        if self._get_tickets_button:
            ba.buttonwidget(edit=self._get_tickets_button,
                            label=ba.charstr(ba.SpecialChar.TICKET) + t_str)
        if self._ticket_count_text:
            ba.textwidget(edit=self._ticket_count_text,
                          text=ba.charstr(ba.SpecialChar.TICKET) + t_str)
Beispiel #19
0
    def on_activate(
        self,
        parent_widget: ba.Widget,
        tab_button: ba.Widget,
        region_width: float,
        region_height: float,
        region_left: float,
        region_bottom: float,
    ) -> ba.Widget:
        party_button_label = ('X' if ba.app.iircade_mode else ba.charstr(
            ba.SpecialChar.TOP_BUTTON))
        message = ba.Lstr(
            resource='gatherWindow.aboutDescriptionText',
            subs=[('${PARTY}', ba.charstr(ba.SpecialChar.PARTY_ICON)),
                  ('${BUTTON}', party_button_label)],
        )

        # Let's not talk about sharing in vr-mode; its tricky to fit more
        # than one head in a VR-headset ;-)
        if not ba.app.vr_mode:
            message = ba.Lstr(
                value='${A}\n\n${B}',
                subs=[('${A}', message),
                      ('${B}',
                       ba.Lstr(resource='gatherWindow.'
                               'aboutDescriptionLocalMultiplayerExtraText'))])
        string_height = 400
        include_invite = True
        msc_scale = 1.1
        c_height_2 = min(region_height, string_height * msc_scale + 100)
        try_tickets = _ba.get_v1_account_misc_read_val('friendTryTickets',
                                                       None)
        if try_tickets is None:
            include_invite = False
        self._container = ba.containerwidget(
            parent=parent_widget,
            position=(region_left,
                      region_bottom + (region_height - c_height_2) * 0.5),
            size=(region_width, c_height_2),
            background=False,
            selectable=include_invite)
        ba.widget(edit=self._container, up_widget=tab_button)

        ba.textwidget(parent=self._container,
                      position=(region_width * 0.5, c_height_2 *
                                (0.58 if include_invite else 0.5)),
                      color=(0.6, 1.0, 0.6),
                      scale=msc_scale,
                      size=(0, 0),
                      maxwidth=region_width * 0.9,
                      max_height=c_height_2 * (0.7 if include_invite else 0.9),
                      h_align='center',
                      v_align='center',
                      text=message)

        if include_invite:
            ba.textwidget(parent=self._container,
                          position=(region_width * 0.57, 35),
                          color=(0, 1, 0),
                          scale=0.6,
                          size=(0, 0),
                          maxwidth=region_width * 0.5,
                          h_align='right',
                          v_align='center',
                          flatness=1.0,
                          text=ba.Lstr(
                              resource='gatherWindow.inviteAFriendText',
                              subs=[('${COUNT}', str(try_tickets))]))
            ba.buttonwidget(
                parent=self._container,
                position=(region_width * 0.59, 10),
                size=(230, 50),
                color=(0.54, 0.42, 0.56),
                textcolor=(0, 1, 0),
                label=ba.Lstr(resource='gatherWindow.inviteFriendsText',
                              fallback_resource=(
                                  'gatherWindow.getFriendInviteCodeText')),
                autoselect=True,
                on_activate_call=ba.WeakCall(self._invite_to_try_press),
                up_widget=tab_button)
        return self._container
Beispiel #20
0
 def _get_custom_logo_tex_name(self) -> Optional[str]:
     if _ba.get_v1_account_misc_read_val('easter', False):
         return 'logoEaster'
     return None
Beispiel #21
0
 def power_ranking_value(self) -> int:
     """Get the power-ranking award value for this achievement."""
     val: int = _ba.get_v1_account_misc_read_val(
         'achLeaguePoints.' + self._name, self._award)
     assert isinstance(val, int)
     return val
Beispiel #22
0
    def _refresh(self) -> None:
        # pylint: disable=too-many-statements

        # (re)create the sub-container if need be..
        if self._subcontainer is not None:
            self._subcontainer.delete()
        self._subcontainer = ba.containerwidget(
            parent=self._scrollwidget,
            size=(self._subcontainerwidth, self._subcontainerheight),
            background=False)

        w_parent = self._subcontainer
        v = self._subcontainerheight - 20

        v -= 0

        h2 = 80
        v2 = v - 60
        worth_color = (0.6, 0.6, 0.65)
        tally_color = (0.5, 0.6, 0.8)
        spc = 43

        h_offs_tally = 150
        tally_maxwidth = 120
        v2 -= 70

        ba.textwidget(parent=w_parent,
                      position=(h2 - 60, v2 + 106),
                      size=(0, 0),
                      flatness=1.0,
                      shadow=0.0,
                      text=ba.Lstr(resource='coopSelectWindow.pointsText'),
                      h_align='left',
                      v_align='center',
                      scale=0.8,
                      color=(1, 1, 1, 0.3),
                      maxwidth=200)

        self._power_ranking_achievements_button = ba.buttonwidget(
            parent=w_parent,
            position=(h2 - 60, v2 + 10),
            size=(200, 80),
            icon=ba.gettexture('achievementsIcon'),
            autoselect=True,
            on_activate_call=ba.WeakCall(self._on_achievements_press),
            up_widget=self._back_button,
            left_widget=self._back_button,
            color=(0.5, 0.5, 0.6),
            textcolor=(0.7, 0.7, 0.8),
            label='')

        self._power_ranking_achievement_total_text = ba.textwidget(
            parent=w_parent,
            position=(h2 + h_offs_tally, v2 + 45),
            size=(0, 0),
            flatness=1.0,
            shadow=0.0,
            text='-',
            h_align='left',
            v_align='center',
            scale=0.8,
            color=tally_color,
            maxwidth=tally_maxwidth)

        v2 -= 80

        self._power_ranking_trophies_button = ba.buttonwidget(
            parent=w_parent,
            position=(h2 - 60, v2 + 10),
            size=(200, 80),
            icon=ba.gettexture('medalSilver'),
            autoselect=True,
            on_activate_call=ba.WeakCall(self._on_trophies_press),
            left_widget=self._back_button,
            color=(0.5, 0.5, 0.6),
            textcolor=(0.7, 0.7, 0.8),
            label='')
        self._power_ranking_trophies_total_text = ba.textwidget(
            parent=w_parent,
            position=(h2 + h_offs_tally, v2 + 45),
            size=(0, 0),
            flatness=1.0,
            shadow=0.0,
            text='-',
            h_align='left',
            v_align='center',
            scale=0.8,
            color=tally_color,
            maxwidth=tally_maxwidth)

        v2 -= 100

        ba.textwidget(
            parent=w_parent,
            position=(h2 - 60, v2 + 86),
            size=(0, 0),
            flatness=1.0,
            shadow=0.0,
            text=ba.Lstr(resource='coopSelectWindow.multipliersText'),
            h_align='left',
            v_align='center',
            scale=0.8,
            color=(1, 1, 1, 0.3),
            maxwidth=200)

        self._activity_mult_button: Optional[ba.Widget]
        if _ba.get_v1_account_misc_read_val('act', False):
            self._activity_mult_button = ba.buttonwidget(
                parent=w_parent,
                position=(h2 - 60, v2 + 10),
                size=(200, 60),
                icon=ba.gettexture('heart'),
                icon_color=(0.5, 0, 0.5),
                label=ba.Lstr(resource='coopSelectWindow.activityText'),
                autoselect=True,
                on_activate_call=ba.WeakCall(self._on_activity_mult_press),
                left_widget=self._back_button,
                color=(0.5, 0.5, 0.6),
                textcolor=(0.7, 0.7, 0.8))

            self._activity_mult_text = ba.textwidget(
                parent=w_parent,
                position=(h2 + h_offs_tally, v2 + 40),
                size=(0, 0),
                flatness=1.0,
                shadow=0.0,
                text='-',
                h_align='left',
                v_align='center',
                scale=0.8,
                color=tally_color,
                maxwidth=tally_maxwidth)
            v2 -= 65
        else:
            self._activity_mult_button = None

        self._pro_mult_button = ba.buttonwidget(
            parent=w_parent,
            position=(h2 - 60, v2 + 10),
            size=(200, 60),
            icon=ba.gettexture('logo'),
            icon_color=(0.3, 0, 0.3),
            label=ba.Lstr(resource='store.bombSquadProNameText',
                          subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                                ]),
            autoselect=True,
            on_activate_call=ba.WeakCall(self._on_pro_mult_press),
            left_widget=self._back_button,
            color=(0.5, 0.5, 0.6),
            textcolor=(0.7, 0.7, 0.8))

        self._pro_mult_text = ba.textwidget(parent=w_parent,
                                            position=(h2 + h_offs_tally,
                                                      v2 + 40),
                                            size=(0, 0),
                                            flatness=1.0,
                                            shadow=0.0,
                                            text='-',
                                            h_align='left',
                                            v_align='center',
                                            scale=0.8,
                                            color=tally_color,
                                            maxwidth=tally_maxwidth)
        v2 -= 30

        v2 -= spc
        ba.textwidget(parent=w_parent,
                      position=(h2 + h_offs_tally - 10 - 40, v2 + 35),
                      size=(0, 0),
                      flatness=1.0,
                      shadow=0.0,
                      text=ba.Lstr(resource='finalScoreText'),
                      h_align='right',
                      v_align='center',
                      scale=0.9,
                      color=worth_color,
                      maxwidth=150)
        self._power_ranking_total_text = ba.textwidget(
            parent=w_parent,
            position=(h2 + h_offs_tally - 40, v2 + 35),
            size=(0, 0),
            flatness=1.0,
            shadow=0.0,
            text='-',
            h_align='left',
            v_align='center',
            scale=0.9,
            color=tally_color,
            maxwidth=tally_maxwidth)

        self._season_show_text = ba.textwidget(
            parent=w_parent,
            position=(390 - 15, v - 20),
            size=(0, 0),
            color=(0.6, 0.6, 0.7),
            maxwidth=200,
            text=ba.Lstr(resource='showText'),
            h_align='right',
            v_align='center',
            scale=0.8,
            shadow=0,
            flatness=1.0)

        self._league_title_text = ba.textwidget(parent=w_parent,
                                                position=(470, v - 97),
                                                size=(0, 0),
                                                color=(0.6, 0.6, 0.7),
                                                maxwidth=230,
                                                text='',
                                                h_align='center',
                                                v_align='center',
                                                scale=0.9,
                                                shadow=0,
                                                flatness=1.0)

        self._league_text_scale = 1.8
        self._league_text_maxwidth = 210
        self._league_text = ba.textwidget(parent=w_parent,
                                          position=(470, v - 140),
                                          size=(0, 0),
                                          color=(1, 1, 1),
                                          maxwidth=self._league_text_maxwidth,
                                          text='-',
                                          h_align='center',
                                          v_align='center',
                                          scale=self._league_text_scale,
                                          shadow=1.0,
                                          flatness=1.0)
        self._league_number_base_pos = (470, v - 140)
        self._league_number_text = ba.textwidget(parent=w_parent,
                                                 position=(470, v - 140),
                                                 size=(0, 0),
                                                 color=(1, 1, 1),
                                                 maxwidth=100,
                                                 text='',
                                                 h_align='left',
                                                 v_align='center',
                                                 scale=0.8,
                                                 shadow=1.0,
                                                 flatness=1.0)

        self._your_power_ranking_text = ba.textwidget(parent=w_parent,
                                                      position=(470,
                                                                v - 142 - 70),
                                                      size=(0, 0),
                                                      color=(0.6, 0.6, 0.7),
                                                      maxwidth=230,
                                                      text='',
                                                      h_align='center',
                                                      v_align='center',
                                                      scale=0.9,
                                                      shadow=0,
                                                      flatness=1.0)

        self._to_ranked_text = ba.textwidget(parent=w_parent,
                                             position=(470, v - 250 - 70),
                                             size=(0, 0),
                                             color=(0.6, 0.6, 0.7),
                                             maxwidth=230,
                                             text='',
                                             h_align='center',
                                             v_align='center',
                                             scale=0.8,
                                             shadow=0,
                                             flatness=1.0)

        self._power_ranking_rank_text = ba.textwidget(parent=w_parent,
                                                      position=(473,
                                                                v - 210 - 70),
                                                      size=(0, 0),
                                                      big=False,
                                                      text='-',
                                                      h_align='center',
                                                      v_align='center',
                                                      scale=1.0)

        self._season_ends_text = ba.textwidget(parent=w_parent,
                                               position=(470, v - 380),
                                               size=(0, 0),
                                               color=(0.6, 0.6, 0.6),
                                               maxwidth=230,
                                               text='',
                                               h_align='center',
                                               v_align='center',
                                               scale=0.9,
                                               shadow=0,
                                               flatness=1.0)
        self._trophy_counts_reset_text = ba.textwidget(
            parent=w_parent,
            position=(470, v - 410),
            size=(0, 0),
            color=(0.5, 0.5, 0.5),
            maxwidth=230,
            text='Trophy counts will reset next season.',
            h_align='center',
            v_align='center',
            scale=0.8,
            shadow=0,
            flatness=1.0)

        self._power_ranking_score_widgets = []

        self._power_ranking_score_v = v - 56

        h = 707
        v -= 451

        self._see_more_button = ba.buttonwidget(parent=w_parent,
                                                label=self._rdict.seeMoreText,
                                                position=(h, v),
                                                color=(0.5, 0.5, 0.6),
                                                textcolor=(0.7, 0.7, 0.8),
                                                size=(230, 60),
                                                autoselect=True,
                                                on_activate_call=ba.WeakCall(
                                                    self._on_more_press))
Beispiel #23
0
    def _update_for_league_rank_data(self, data: Optional[dict[str,
                                                               Any]]) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        if not self._root_widget:
            return
        accounts = ba.app.accounts_v1
        in_top = (data is not None and data['rank'] is not None)
        eq_text = self._rdict.powerRankingPointsEqualsText
        pts_txt = self._rdict.powerRankingPointsText
        num_text = ba.Lstr(resource='numberText').evaluate()
        do_percent = False
        finished_season_unranked = False
        self._can_do_more_button = True
        extra_text = ''
        if _ba.get_v1_account_state() != 'signed_in':
            status_text = '(' + ba.Lstr(
                resource='notSignedInText').evaluate() + ')'
        elif in_top:
            assert data is not None
            status_text = num_text.replace('${NUMBER}', str(data['rank']))
        elif data is not None:
            try:
                # handle old seasons where we didn't wind up ranked
                # at the end..
                if not data['scores']:
                    status_text = (
                        self._rdict.powerRankingFinishedSeasonUnrankedText)
                    extra_text = ''
                    finished_season_unranked = True
                    self._can_do_more_button = False
                else:
                    our_points = accounts.get_league_rank_points(data)
                    progress = float(our_points) / max(1,
                                                       data['scores'][-1][1])
                    status_text = str(int(progress * 100.0)) + '%'
                    extra_text = (
                        '\n' +
                        self._rdict.powerRankingPointsToRankedText.replace(
                            '${CURRENT}', str(our_points)).replace(
                                '${REMAINING}', str(data['scores'][-1][1])))
                    do_percent = True
            except Exception:
                ba.print_exception('Error updating power ranking.')
                status_text = self._rdict.powerRankingNotInTopText.replace(
                    '${NUMBER}', str(data['listSize']))
                extra_text = ''
        else:
            status_text = '-'

        self._season = data['s'] if data is not None else None

        v = self._subcontainerheight - 20
        popup_was_selected = False
        if self._season_popup_menu is not None:
            btn = self._season_popup_menu.get_button()
            assert self._subcontainer
            if self._subcontainer.get_selected_child() == btn:
                popup_was_selected = True
            btn.delete()
        season_choices = []
        season_choices_display = []
        did_first = False
        self._is_current_season = False
        if data is not None:
            # build our list of seasons we have available
            for ssn in data['sl']:
                season_choices.append(ssn)
                if ssn != 'a' and not did_first:
                    season_choices_display.append(
                        ba.Lstr(resource='league.currentSeasonText',
                                subs=[('${NUMBER}', ssn)]))
                    did_first = True
                    # if we either did not specify a season or specified the
                    # first, we're looking at the current..
                    if self._season in [ssn, None]:
                        self._is_current_season = True
                elif ssn == 'a':
                    season_choices_display.append(
                        ba.Lstr(resource='league.allTimeText'))
                else:
                    season_choices_display.append(
                        ba.Lstr(resource='league.seasonText',
                                subs=[('${NUMBER}', ssn)]))
            assert self._subcontainer
            self._season_popup_menu = popup_ui.PopupMenu(
                parent=self._subcontainer,
                position=(390, v - 45),
                width=150,
                button_size=(200, 50),
                choices=season_choices,
                on_value_change_call=ba.WeakCall(self._on_season_change),
                choices_display=season_choices_display,
                current_choice=self._season)
            if popup_was_selected:
                ba.containerwidget(
                    edit=self._subcontainer,
                    selected_child=self._season_popup_menu.get_button())
            ba.widget(edit=self._see_more_button, show_buffer_bottom=100)
            ba.widget(edit=self._season_popup_menu.get_button(),
                      up_widget=self._back_button)
            ba.widget(edit=self._back_button,
                      down_widget=self._power_ranking_achievements_button,
                      right_widget=self._season_popup_menu.get_button())

        ba.textwidget(edit=self._league_title_text,
                      text='' if self._season == 'a' else ba.Lstr(
                          resource='league.leagueText'))

        if data is None:
            lname = ''
            lnum = ''
            lcolor = (1, 1, 1)
            self._league_url_arg = ''
        elif self._season == 'a':
            lname = ba.Lstr(resource='league.allTimeText').evaluate()
            lnum = ''
            lcolor = (1, 1, 1)
            self._league_url_arg = ''
        else:
            lnum = ('[' + str(data['l']['i']) + ']') if data['l']['i2'] else ''
            lname = ba.Lstr(translate=('leagueNames',
                                       data['l']['n'])).evaluate()
            lcolor = data['l']['c']
            self._league_url_arg = (data['l']['n'] + '_' +
                                    str(data['l']['i'])).lower()

        to_end_string: Union[ba.Lstr, str]
        if data is None or self._season == 'a' or data['se'] is None:
            to_end_string = ''
            show_season_end = False
        else:
            show_season_end = True
            days_to_end = data['se'][0]
            minutes_to_end = data['se'][1]
            if days_to_end > 0:
                to_end_string = ba.Lstr(resource='league.seasonEndsDaysText',
                                        subs=[('${NUMBER}', str(days_to_end))])
            elif days_to_end == 0 and minutes_to_end >= 60:
                to_end_string = ba.Lstr(resource='league.seasonEndsHoursText',
                                        subs=[('${NUMBER}',
                                               str(minutes_to_end // 60))])
            elif days_to_end == 0 and minutes_to_end >= 0:
                to_end_string = ba.Lstr(
                    resource='league.seasonEndsMinutesText',
                    subs=[('${NUMBER}', str(minutes_to_end))])
            else:
                to_end_string = ba.Lstr(
                    resource='league.seasonEndedDaysAgoText',
                    subs=[('${NUMBER}', str(-(days_to_end + 1)))])

        ba.textwidget(edit=self._season_ends_text, text=to_end_string)
        ba.textwidget(edit=self._trophy_counts_reset_text,
                      text=ba.Lstr(resource='league.trophyCountsResetText')
                      if self._is_current_season and show_season_end else '')

        ba.textwidget(edit=self._league_text, text=lname, color=lcolor)
        l_text_width = min(
            self._league_text_maxwidth,
            _ba.get_string_width(lname, suppress_warning=True) *
            self._league_text_scale)
        ba.textwidget(
            edit=self._league_number_text,
            text=lnum,
            color=lcolor,
            position=(self._league_number_base_pos[0] + l_text_width * 0.5 + 8,
                      self._league_number_base_pos[1] + 10))
        ba.textwidget(
            edit=self._to_ranked_text,
            text=ba.Lstr(resource='coopSelectWindow.toRankedText').evaluate() +
            '' + extra_text if do_percent else '')

        ba.textwidget(
            edit=self._your_power_ranking_text,
            text=ba.Lstr(
                resource='rankText',
                fallback_resource='coopSelectWindow.yourPowerRankingText') if
            (not do_percent) else '')

        ba.textwidget(edit=self._power_ranking_rank_text,
                      position=(473, v - 70 - (170 if do_percent else 220)),
                      text=status_text,
                      big=(in_top or do_percent),
                      scale=3.0 if (in_top or do_percent) else
                      0.7 if finished_season_unranked else 1.0)

        if self._activity_mult_button is not None:
            if data is None or data['act'] is None:
                ba.buttonwidget(edit=self._activity_mult_button,
                                textcolor=(0.7, 0.7, 0.8, 0.5),
                                icon_color=(0.5, 0, 0.5, 0.3))
                ba.textwidget(edit=self._activity_mult_text, text='     -')
            else:
                ba.buttonwidget(edit=self._activity_mult_button,
                                textcolor=(0.7, 0.7, 0.8, 1.0),
                                icon_color=(0.5, 0, 0.5, 1.0))
                # pylint: disable=consider-using-f-string
                ba.textwidget(edit=self._activity_mult_text,
                              text='x ' + ('%.2f' % data['act']))

        have_pro = False if data is None else data['p']
        pro_mult = 1.0 + float(
            _ba.get_v1_account_misc_read_val('proPowerRankingBoost',
                                             0.0)) * 0.01
        # pylint: disable=consider-using-f-string
        ba.textwidget(edit=self._pro_mult_text,
                      text='     -' if
                      (data is None or not have_pro) else 'x ' +
                      ('%.2f' % pro_mult))
        ba.buttonwidget(edit=self._pro_mult_button,
                        textcolor=(0.7, 0.7, 0.8, (1.0 if have_pro else 0.5)),
                        icon_color=(0.5, 0, 0.5) if have_pro else
                        (0.5, 0, 0.5, 0.2))
        ba.buttonwidget(edit=self._power_ranking_achievements_button,
                        label=('' if data is None else
                               (str(data['a']) + ' ')) +
                        ba.Lstr(resource='achievementsText').evaluate())

        # for the achievement value, use the number they gave us for
        # non-current seasons; otherwise calc our own
        total_ach_value = 0
        for ach in ba.app.ach.achievements:
            if ach.complete:
                total_ach_value += ach.power_ranking_value
        if self._season != 'a' and not self._is_current_season:
            if data is not None and 'at' in data:
                total_ach_value = data['at']

        ba.textwidget(edit=self._power_ranking_achievement_total_text,
                      text='-' if data is None else
                      ('+ ' +
                       pts_txt.replace('${NUMBER}', str(total_ach_value))))

        total_trophies_count = (accounts.get_league_rank_points(
            data, 'trophyCount'))
        total_trophies_value = (accounts.get_league_rank_points(
            data, 'trophies'))
        ba.buttonwidget(edit=self._power_ranking_trophies_button,
                        label=('' if data is None else
                               (str(total_trophies_count) + ' ')) +
                        ba.Lstr(resource='trophiesText').evaluate())
        ba.textwidget(
            edit=self._power_ranking_trophies_total_text,
            text='-' if data is None else
            ('+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value))))

        ba.textwidget(
            edit=self._power_ranking_total_text,
            text='-' if data is None else eq_text.replace(
                '${NUMBER}', str(accounts.get_league_rank_points(data))))
        for widget in self._power_ranking_score_widgets:
            widget.delete()
        self._power_ranking_score_widgets = []

        scores = data['scores'] if data is not None else []
        tally_color = (0.5, 0.6, 0.8)
        w_parent = self._subcontainer
        v2 = self._power_ranking_score_v

        for score in scores:
            h2 = 680
            is_us = score[3]
            self._power_ranking_score_widgets.append(
                ba.textwidget(parent=w_parent,
                              position=(h2 - 20, v2),
                              size=(0, 0),
                              color=(1, 1, 1) if is_us else (0.6, 0.6, 0.7),
                              maxwidth=40,
                              flatness=1.0,
                              shadow=0.0,
                              text=num_text.replace('${NUMBER}',
                                                    str(score[0])),
                              h_align='right',
                              v_align='center',
                              scale=0.5))
            self._power_ranking_score_widgets.append(
                ba.textwidget(parent=w_parent,
                              position=(h2 + 20, v2),
                              size=(0, 0),
                              color=(1, 1, 1) if is_us else tally_color,
                              maxwidth=60,
                              text=str(score[1]),
                              flatness=1.0,
                              shadow=0.0,
                              h_align='center',
                              v_align='center',
                              scale=0.7))
            txt = ba.textwidget(parent=w_parent,
                                position=(h2 + 60, v2 - (28 * 0.5) / 0.9),
                                size=(210 / 0.9, 28),
                                color=(1, 1, 1) if is_us else (0.6, 0.6, 0.6),
                                maxwidth=210,
                                flatness=1.0,
                                shadow=0.0,
                                autoselect=True,
                                selectable=True,
                                click_activate=True,
                                text=score[2],
                                h_align='left',
                                v_align='center',
                                scale=0.9)
            self._power_ranking_score_widgets.append(txt)
            ba.textwidget(edit=txt,
                          on_activate_call=ba.Call(self._show_account_info,
                                                   score[4], txt))
            assert self._season_popup_menu is not None
            ba.widget(edit=txt,
                      left_widget=self._season_popup_menu.get_button())
            v2 -= 28
Beispiel #24
0
    def _refresh(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui import confirm

        account_state = _ba.get_v1_account_state()
        account_type = (_ba.get_v1_account_type()
                        if account_state == 'signed_in' else 'unknown')

        is_google = account_type == 'Google Play'

        show_local_signed_in_as = False
        local_signed_in_as_space = 50.0

        show_signed_in_as = self._signed_in
        signed_in_as_space = 95.0

        show_sign_in_benefits = not self._signed_in
        sign_in_benefits_space = 80.0

        show_signing_in_text = account_state == 'signing_in'
        signing_in_text_space = 80.0

        show_google_play_sign_in_button = (account_state == 'signed_out'
                                           and 'Google Play'
                                           in self._show_sign_in_buttons)
        show_game_circle_sign_in_button = (account_state == 'signed_out'
                                           and 'Game Circle'
                                           in self._show_sign_in_buttons)
        show_device_sign_in_button = (account_state == 'signed_out' and 'Local'
                                      in self._show_sign_in_buttons)
        show_v2_sign_in_button = (account_state == 'signed_out'
                                  and 'V2' in self._show_sign_in_buttons)
        sign_in_button_space = 70.0

        show_game_service_button = (self._signed_in and account_type
                                    in ['Game Center', 'Game Circle'])
        game_service_button_space = 60.0

        show_linked_accounts_text = (self._signed_in
                                     and _ba.get_v1_account_misc_read_val(
                                         'allowAccountLinking2', False))
        linked_accounts_text_space = 60.0

        show_achievements_button = (
            self._signed_in
            and account_type in ('Google Play', 'Alibaba', 'Local', 'OUYA'))
        achievements_button_space = 60.0

        show_achievements_text = (self._signed_in
                                  and not show_achievements_button)
        achievements_text_space = 27.0

        show_leaderboards_button = (self._signed_in and is_google)
        leaderboards_button_space = 60.0

        show_campaign_progress = self._signed_in
        campaign_progress_space = 27.0

        show_tickets = self._signed_in
        tickets_space = 27.0

        show_reset_progress_button = False
        reset_progress_button_space = 70.0

        show_player_profiles_button = self._signed_in
        player_profiles_button_space = 100.0

        show_link_accounts_button = (self._signed_in
                                     and _ba.get_v1_account_misc_read_val(
                                         'allowAccountLinking2', False))
        link_accounts_button_space = 70.0

        show_unlink_accounts_button = show_link_accounts_button
        unlink_accounts_button_space = 90.0

        show_sign_out_button = (self._signed_in and account_type
                                in ['Local', 'Google Play', 'V2'])
        sign_out_button_space = 70.0

        show_cancel_v2_sign_in_button = (
            account_state == 'signing_in'
            and ba.app.accounts_v2.have_primary_credentials())
        cancel_v2_sign_in_button_space = 70.0

        if self._subcontainer is not None:
            self._subcontainer.delete()
        self._sub_height = 60.0
        if show_local_signed_in_as:
            self._sub_height += local_signed_in_as_space
        if show_signed_in_as:
            self._sub_height += signed_in_as_space
        if show_signing_in_text:
            self._sub_height += signing_in_text_space
        if show_google_play_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_game_circle_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_device_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_v2_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_game_service_button:
            self._sub_height += game_service_button_space
        if show_linked_accounts_text:
            self._sub_height += linked_accounts_text_space
        if show_achievements_text:
            self._sub_height += achievements_text_space
        if show_achievements_button:
            self._sub_height += achievements_button_space
        if show_leaderboards_button:
            self._sub_height += leaderboards_button_space
        if show_campaign_progress:
            self._sub_height += campaign_progress_space
        if show_tickets:
            self._sub_height += tickets_space
        if show_sign_in_benefits:
            self._sub_height += sign_in_benefits_space
        if show_reset_progress_button:
            self._sub_height += reset_progress_button_space
        if show_player_profiles_button:
            self._sub_height += player_profiles_button_space
        if show_link_accounts_button:
            self._sub_height += link_accounts_button_space
        if show_unlink_accounts_button:
            self._sub_height += unlink_accounts_button_space
        if show_sign_out_button:
            self._sub_height += sign_out_button_space
        if show_cancel_v2_sign_in_button:
            self._sub_height += cancel_v2_sign_in_button_space
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False,
                                                claims_left_right=True,
                                                claims_tab=True,
                                                selection_loops_to_parent=True)

        first_selectable = None
        v = self._sub_height - 10.0

        if show_local_signed_in_as:
            v -= local_signed_in_as_space * 0.6
            ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                text=ba.Lstr(
                    resource='accountSettingsWindow.deviceSpecificAccountText',
                    subs=[('${NAME}', _ba.get_v1_account_display_string())]),
                scale=0.7,
                color=(0.5, 0.5, 0.6),
                maxwidth=self._sub_width * 0.9,
                flatness=1.0,
                h_align='center',
                v_align='center')
            v -= local_signed_in_as_space * 0.4

        self._account_name_text: Optional[ba.Widget]
        if show_signed_in_as:
            v -= signed_in_as_space * 0.2
            txt = ba.Lstr(
                resource='accountSettingsWindow.youAreSignedInAsText',
                fallback_resource='accountSettingsWindow.youAreLoggedInAsText')
            ba.textwidget(parent=self._subcontainer,
                          position=(self._sub_width * 0.5, v),
                          size=(0, 0),
                          text=txt,
                          scale=0.9,
                          color=ba.app.ui.title_color,
                          maxwidth=self._sub_width * 0.9,
                          h_align='center',
                          v_align='center')
            v -= signed_in_as_space * 0.4
            self._account_name_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=1.5,
                maxwidth=self._sub_width * 0.9,
                res_scale=1.5,
                color=(1, 1, 1, 1),
                h_align='center',
                v_align='center')
            self._refresh_account_name_text()
            v -= signed_in_as_space * 0.4
        else:
            self._account_name_text = None

        if self._back_button is None:
            bbtn = _ba.get_special_widget('back_button')
        else:
            bbtn = self._back_button

        if show_sign_in_benefits:
            v -= sign_in_benefits_space
            app = ba.app
            extra: Optional[Union[str, ba.Lstr]]
            if (app.platform in ['mac', 'ios']
                    and app.subplatform == 'appstore'):
                extra = ba.Lstr(
                    value='\n${S}',
                    subs=[('${S}',
                           ba.Lstr(resource='signInWithGameCenterText'))])
            else:
                extra = ''

            ba.textwidget(parent=self._subcontainer,
                          position=(self._sub_width * 0.5,
                                    v + sign_in_benefits_space * 0.4),
                          size=(0, 0),
                          text=ba.Lstr(value='${A}${B}',
                                       subs=[('${A}',
                                              ba.Lstr(resource=self._r +
                                                      '.signInInfoText')),
                                             ('${B}', extra)]),
                          max_height=sign_in_benefits_space * 0.9,
                          scale=0.9,
                          color=(0.75, 0.7, 0.8),
                          maxwidth=self._sub_width * 0.8,
                          h_align='center',
                          v_align='center')

        if show_signing_in_text:
            v -= signing_in_text_space

            ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5,
                          v + signing_in_text_space * 0.5),
                size=(0, 0),
                text=ba.Lstr(resource='accountSettingsWindow.signingInText'),
                scale=0.9,
                color=(0, 1, 0),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')

        if show_google_play_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_google_play_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(
                    value='${A}${B}',
                    subs=[('${A}',
                           ba.charstr(ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO)),
                          ('${B}',
                           ba.Lstr(resource=self._r +
                                   '.signInWithGooglePlayText'))]),
                on_activate_call=lambda: self._sign_in_press('Google Play'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_game_circle_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_game_circle_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(
                                         ba.SpecialChar.GAME_CIRCLE_LOGO)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithGameCircleText'))]),
                on_activate_call=lambda: self._sign_in_press('Game Circle'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_v2_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_v2_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label='',
                on_activate_call=self._v2_sign_in_press)
            ba.textwidget(
                parent=self._subcontainer,
                draw_controller=btn,
                h_align='center',
                v_align='center',
                size=(0, 0),
                position=(self._sub_width * 0.5, v + 17),
                text=ba.Lstr(
                    value='${A}${B}',
                    subs=[('${A}', ba.charstr(ba.SpecialChar.V2_LOGO)),
                          ('${B}',
                           ba.Lstr(resource=self._r + '.signInWithV2Text'))]),
                maxwidth=button_width * 0.8,
                color=(0.75, 1.0, 0.7))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4),
                          text=ba.Lstr(resource=self._r +
                                       '.signInWithV2InfoText'),
                          flatness=1.0,
                          scale=0.57,
                          maxwidth=button_width * 0.9,
                          color=(0.55, 0.8, 0.5))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_device_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_device_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label='',
                on_activate_call=lambda: self._sign_in_press('Local'))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v + 17),
                          text=ba.Lstr(
                              value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(ba.SpecialChar.LOCAL_ACCOUNT)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithDeviceText'))]),
                          maxwidth=button_width * 0.8,
                          color=(0.75, 1.0, 0.7))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4),
                          text=ba.Lstr(resource=self._r +
                                       '.signInWithDeviceInfoText'),
                          flatness=1.0,
                          scale=0.57,
                          maxwidth=button_width * 0.9,
                          color=(0.55, 0.8, 0.5))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_player_profiles_button:
            button_width = 300
            v -= player_profiles_button_space
            self._player_profiles_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v + 30),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(resource='playerProfilesWindow.titleText'),
                color=(0.55, 0.5, 0.6),
                icon=ba.gettexture('cuteSpaz'),
                textcolor=(0.75, 0.7, 0.8),
                on_activate_call=self._player_profiles_press)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=0)

        # the button to go to OS-Specific leaderboards/high-score-lists/etc.
        if show_game_service_button:
            button_width = 300
            v -= game_service_button_space * 0.85
            account_type = _ba.get_v1_account_type()
            if account_type == 'Game Center':
                account_type_name = ba.Lstr(resource='gameCenterText')
            elif account_type == 'Game Circle':
                account_type_name = ba.Lstr(resource='gameCircleText')
            else:
                raise ValueError("unknown account type: '" +
                                 str(account_type) + "'")
            self._game_service_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                on_activate_call=_ba.show_online_score_ui,
                size=(button_width, 50),
                label=account_type_name)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= game_service_button_space * 0.15
        else:
            self.game_service_button = None

        self._achievements_text: Optional[ba.Widget]
        if show_achievements_text:
            v -= achievements_text_space * 0.5
            self._achievements_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')
            v -= achievements_text_space * 0.5
        else:
            self._achievements_text = None

        self._achievements_button: Optional[ba.Widget]
        if show_achievements_button:
            button_width = 300
            v -= achievements_button_space * 0.85
            self._achievements_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                icon=ba.gettexture('googlePlayAchievementsIcon'
                                   if is_google else 'achievementsIcon'),
                icon_color=(0.8, 0.95, 0.7) if is_google else (0.85, 0.8, 0.9),
                on_activate_call=self._on_achievements_press,
                size=(button_width, 50),
                label='')
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= achievements_button_space * 0.15
        else:
            self._achievements_button = None

        if show_achievements_text or show_achievements_button:
            self._refresh_achievements()

        self._leaderboards_button: Optional[ba.Widget]
        if show_leaderboards_button:
            button_width = 300
            v -= leaderboards_button_space * 0.85
            self._leaderboards_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                icon=ba.gettexture('googlePlayLeaderboardsIcon'),
                icon_color=(0.8, 0.95, 0.7),
                on_activate_call=self._on_leaderboards_press,
                size=(button_width, 50),
                label=ba.Lstr(resource='leaderboardsText'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= leaderboards_button_space * 0.15
        else:
            self._leaderboards_button = None

        self._campaign_progress_text: Optional[ba.Widget]
        if show_campaign_progress:
            v -= campaign_progress_space * 0.5
            self._campaign_progress_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')
            v -= campaign_progress_space * 0.5
            self._refresh_campaign_progress_text()
        else:
            self._campaign_progress_text = None

        self._tickets_text: Optional[ba.Widget]
        if show_tickets:
            v -= tickets_space * 0.5
            self._tickets_text = ba.textwidget(parent=self._subcontainer,
                                               position=(self._sub_width * 0.5,
                                                         v),
                                               size=(0, 0),
                                               scale=0.9,
                                               color=(0.75, 0.7, 0.8),
                                               maxwidth=self._sub_width * 0.8,
                                               flatness=1.0,
                                               h_align='center',
                                               v_align='center')
            v -= tickets_space * 0.5
            self._refresh_tickets_text()

        else:
            self._tickets_text = None

        # bit of spacing before the reset/sign-out section
        v -= 5

        button_width = 250
        if show_reset_progress_button:
            confirm_text = (ba.Lstr(resource=self._r +
                                    '.resetProgressConfirmText')
                            if self._can_reset_achievements else ba.Lstr(
                                resource=self._r +
                                '.resetProgressConfirmNoAchievementsText'))
            v -= reset_progress_button_space
            self._reset_progress_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(resource=self._r + '.resetProgressText'),
                on_activate_call=lambda: confirm.ConfirmWindow(
                    text=confirm_text,
                    width=500,
                    height=200,
                    action=self._reset_progress))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)

        self._linked_accounts_text: Optional[ba.Widget]
        if show_linked_accounts_text:
            v -= linked_accounts_text_space * 0.8
            self._linked_accounts_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.95,
                h_align='center',
                v_align='center')
            v -= linked_accounts_text_space * 0.2
            self._update_linked_accounts_text()
        else:
            self._linked_accounts_text = None

        if show_link_accounts_button:
            v -= link_accounts_button_space
            self._link_accounts_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                autoselect=True,
                size=(button_width, 60),
                label='',
                color=(0.55, 0.5, 0.6),
                on_activate_call=self._link_accounts_press)
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v + 17 + 20),
                          text=ba.Lstr(resource=self._r + '.linkAccountsText'),
                          maxwidth=button_width * 0.8,
                          color=(0.75, 0.7, 0.8))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4 + 20),
                          text=ba.Lstr(resource=self._r +
                                       '.linkAccountsInfoText'),
                          flatness=1.0,
                          scale=0.5,
                          maxwidth=button_width * 0.8,
                          color=(0.75, 0.7, 0.8))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50)

        self._unlink_accounts_button: Optional[ba.Widget]
        if show_unlink_accounts_button:
            v -= unlink_accounts_button_space
            self._unlink_accounts_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v + 25),
                autoselect=True,
                size=(button_width, 60),
                label='',
                color=(0.55, 0.5, 0.6),
                on_activate_call=self._unlink_accounts_press)
            self._unlink_accounts_button_label = ba.textwidget(
                parent=self._subcontainer,
                draw_controller=btn,
                h_align='center',
                v_align='center',
                size=(0, 0),
                position=(self._sub_width * 0.5, v + 55),
                text=ba.Lstr(resource=self._r + '.unlinkAccountsText'),
                maxwidth=button_width * 0.8,
                color=(0.75, 0.7, 0.8))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50)
            self._update_unlink_accounts_button()
        else:
            self._unlink_accounts_button = None

        if show_sign_out_button:
            v -= sign_out_button_space
            self._sign_out_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                size=(button_width, 60),
                label=ba.Lstr(resource=self._r + '.signOutText'),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                on_activate_call=self._sign_out_press)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=15)

        if show_cancel_v2_sign_in_button:
            v -= cancel_v2_sign_in_button_space
            self._cancel_v2_sign_in_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                size=(button_width, 60),
                label=ba.Lstr(resource='cancelText'),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                on_activate_call=self._cancel_v2_sign_in_press)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=15)

        # Whatever the topmost selectable thing is, we want it to scroll all
        # the way up when we select it.
        if first_selectable is not None:
            ba.widget(edit=first_selectable,
                      up_widget=bbtn,
                      show_buffer_top=400)
            # (this should re-scroll us to the top..)
            ba.containerwidget(edit=self._subcontainer,
                               visible_child=first_selectable)
        self._needs_refresh = False
Beispiel #25
0
    def update(self, index: int, party: PartyEntry, sub_scroll_width: float,
               sub_scroll_height: float, lineheight: float,
               columnwidget: ba.Widget, join_text: ba.Widget,
               filter_text: ba.Widget, existing_selection: Optional[Selection],
               tab: PublicGatherTab) -> None:
        """Update for the given data."""
        # pylint: disable=too-many-locals

        # Quick-out: if we've been marked clean for a certain index and
        # we're still at that index, we're done.
        if party.clean_display_index == index:
            return

        ping_good = _ba.get_v1_account_misc_read_val('pingGood', 100)
        ping_med = _ba.get_v1_account_misc_read_val('pingMed', 500)

        self._clear()
        hpos = 20
        vpos = sub_scroll_height - lineheight * index - 50
        self._name_widget = ba.textwidget(
            text=ba.Lstr(value=party.name),
            parent=columnwidget,
            size=(sub_scroll_width * 0.63, 20),
            position=(0 + hpos, 4 + vpos),
            selectable=True,
            on_select_call=ba.WeakCall(
                tab.set_public_party_selection,
                Selection(party.get_key(), SelectionComponent.NAME)),
            on_activate_call=ba.WeakCall(tab.on_public_party_activate, party),
            click_activate=True,
            maxwidth=sub_scroll_width * 0.45,
            corner_scale=1.4,
            autoselect=True,
            color=(1, 1, 1, 0.3 if party.ping is None else 1.0),
            h_align='left',
            v_align='center')
        ba.widget(edit=self._name_widget,
                  left_widget=join_text,
                  show_buffer_top=64.0,
                  show_buffer_bottom=64.0)
        if existing_selection == Selection(party.get_key(),
                                           SelectionComponent.NAME):
            ba.containerwidget(edit=columnwidget,
                               selected_child=self._name_widget)
        if party.stats_addr:
            url = party.stats_addr.replace(
                '${ACCOUNT}',
                _ba.get_v1_account_misc_read_val_2('resolvedAccountID',
                                                   'UNKNOWN'))
            self._stats_button = ba.buttonwidget(
                color=(0.3, 0.6, 0.94),
                textcolor=(1.0, 1.0, 1.0),
                label=ba.Lstr(resource='statsText'),
                parent=columnwidget,
                autoselect=True,
                on_activate_call=ba.Call(ba.open_url, url),
                on_select_call=ba.WeakCall(
                    tab.set_public_party_selection,
                    Selection(party.get_key(),
                              SelectionComponent.STATS_BUTTON)),
                size=(120, 40),
                position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
                scale=0.9)
            if existing_selection == Selection(
                    party.get_key(), SelectionComponent.STATS_BUTTON):
                ba.containerwidget(edit=columnwidget,
                                   selected_child=self._stats_button)

        self._size_widget = ba.textwidget(
            text=str(party.size) + '/' + str(party.size_max),
            parent=columnwidget,
            size=(0, 0),
            position=(sub_scroll_width * 0.86 + hpos, 20 + vpos),
            scale=0.7,
            color=(0.8, 0.8, 0.8),
            h_align='right',
            v_align='center')

        if index == 0:
            ba.widget(edit=self._name_widget, up_widget=filter_text)
            if self._stats_button:
                ba.widget(edit=self._stats_button, up_widget=filter_text)

        self._ping_widget = ba.textwidget(parent=columnwidget,
                                          size=(0, 0),
                                          position=(sub_scroll_width * 0.94 +
                                                    hpos, 20 + vpos),
                                          scale=0.7,
                                          h_align='right',
                                          v_align='center')
        if party.ping is None:
            ba.textwidget(edit=self._ping_widget,
                          text='-',
                          color=(0.5, 0.5, 0.5))
        else:
            ba.textwidget(edit=self._ping_widget,
                          text=str(int(party.ping)),
                          color=(0, 1, 0) if party.ping <= ping_good else
                          (1, 1, 0) if party.ping <= ping_med else (1, 0, 0))

        party.clean_display_index = index
Beispiel #26
0
    def __init__(self,
                 items: list[str],
                 transition: str = 'in_right',
                 header_text: ba.Lstr = None):
        from ba.internal import get_store_item_display_size
        from bastd.ui.store import item as storeitemui
        if header_text is None:
            header_text = ba.Lstr(resource='unlockThisText',
                                  fallback_resource='unlockThisInTheStoreText')
        if len(items) != 1:
            raise ValueError('expected exactly 1 item')
        self._items = list(items)
        self._width = 580
        self._height = 520
        uiscale = ba.app.ui.uiscale
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            toolbar_visibility='menu_currency',
            scale=(1.2 if uiscale is ba.UIScale.SMALL else
                   1.1 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -15) if uiscale is ba.UIScale.SMALL else (0, 0)))
        self._is_double = False
        self._title_text = ba.textwidget(parent=self._root_widget,
                                         position=(self._width * 0.5,
                                                   self._height - 30),
                                         size=(0, 0),
                                         text=header_text,
                                         h_align='center',
                                         v_align='center',
                                         maxwidth=self._width * 0.9 - 120,
                                         scale=1.2,
                                         color=(1, 0.8, 0.3, 1))
        size = get_store_item_display_size(items[0])
        display: dict[str, Any] = {}
        storeitemui.instantiate_store_item_display(
            items[0],
            display,
            parent_widget=self._root_widget,
            b_pos=(self._width * 0.5 - size[0] * 0.5 + 10 -
                   ((size[0] * 0.5 + 30) if self._is_double else 0),
                   self._height * 0.5 - size[1] * 0.5 + 30 +
                   (20 if self._is_double else 0)),
            b_width=size[0],
            b_height=size[1],
            button=False)

        # Wire up the parts we need.
        if self._is_double:
            pass  # not working
        else:
            if self._items == ['pro']:
                price_str = _ba.get_price(self._items[0])
                pyoffs = -15
            else:
                pyoffs = 0
                price = self._price = _ba.get_v1_account_misc_read_val(
                    'price.' + str(items[0]), -1)
                price_str = ba.charstr(ba.SpecialChar.TICKET) + str(price)
            self._price_text = ba.textwidget(parent=self._root_widget,
                                             position=(self._width * 0.5,
                                                       150 + pyoffs),
                                             size=(0, 0),
                                             text=price_str,
                                             h_align='center',
                                             v_align='center',
                                             maxwidth=self._width * 0.9,
                                             scale=1.4,
                                             color=(0.2, 1, 0.2))

        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)

        self._cancel_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(50, 40),
            size=(150, 60),
            scale=1.0,
            on_activate_call=self._cancel,
            autoselect=True,
            label=ba.Lstr(resource='cancelText'))
        self._purchase_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(self._width - 200, 40),
            size=(150, 60),
            scale=1.0,
            on_activate_call=self._purchase,
            autoselect=True,
            label=ba.Lstr(resource='store.purchaseText'))

        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button,
                           start_button=self._purchase_button,
                           selected_child=self._purchase_button)
Beispiel #27
0
def instantiate_store_item_display(item_name: str,
                                   item: dict[str, Any],
                                   parent_widget: ba.Widget,
                                   b_pos: tuple[float, float],
                                   b_width: float,
                                   b_height: float,
                                   boffs_h: float = 0.0,
                                   boffs_h2: float = 0.0,
                                   boffs_v2: float = 0,
                                   delay: float = 0.0,
                                   button: bool = True) -> None:
    """(internal)"""
    # pylint: disable=too-many-statements
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-locals
    from ba.internal import (get_store_item, get_store_item_name_translated,
                             get_clean_price)
    del boffs_h  # unused arg
    del boffs_h2  # unused arg
    del boffs_v2  # unused arg
    item_info = get_store_item(item_name)
    title_v = 0.24
    price_v = 0.145
    base_text_scale = 1.0

    item['name'] = title = get_store_item_name_translated(item_name)

    btn: Optional[ba.Widget]
    if button:
        item['button'] = btn = ba.buttonwidget(parent=parent_widget,
                                               position=b_pos,
                                               transition_delay=delay,
                                               show_buffer_top=76.0,
                                               enable_sound=False,
                                               button_type='square',
                                               size=(b_width, b_height),
                                               autoselect=True,
                                               label='')
        ba.widget(edit=btn, show_buffer_bottom=76.0)
    else:
        btn = None

    b_offs_x = -0.015 * b_width
    check_pos = 0.76

    icon_tex = None
    tint_tex = None
    tint_color = None
    tint2_color = None
    tex_name: Optional[str] = None
    desc: Optional[str] = None
    modes: Optional[ba.Lstr] = None

    if item_name.startswith('characters.'):
        character = ba.app.spaz_appearances[item_info['character']]
        tint_color = (
            item_info['color'] if 'color' in item_info else
            character.default_color if character.default_color is not None else
            (1, 1, 1))
        tint2_color = (item_info['highlight'] if 'highlight' in item_info else
                       character.default_highlight if
                       character.default_highlight is not None else (1, 1, 1))
        icon_tex = character.icon_texture
        tint_tex = character.icon_mask_texture
        title_v = 0.255
        price_v = 0.145
    elif item_name in ['upgrades.pro', 'pro']:
        base_text_scale = 0.6
        title_v = 0.85
        price_v = 0.15
    elif item_name.startswith('maps.'):
        map_type = item_info['map_type']
        tex_name = map_type.get_preview_texture_name()
        title_v = 0.312
        price_v = 0.17

    elif item_name.startswith('games.'):
        gametype = item_info['gametype']
        modes_l = []
        if gametype.supports_session_type(ba.CoopSession):
            modes_l.append(ba.Lstr(resource='playModes.coopText'))
        if gametype.supports_session_type(ba.DualTeamSession):
            modes_l.append(ba.Lstr(resource='playModes.teamsText'))
        if gametype.supports_session_type(ba.FreeForAllSession):
            modes_l.append(ba.Lstr(resource='playModes.freeForAllText'))

        if len(modes_l) == 3:
            modes = ba.Lstr(value='${A}, ${B}, ${C}',
                            subs=[('${A}', modes_l[0]), ('${B}', modes_l[1]),
                                  ('${C}', modes_l[2])])
        elif len(modes_l) == 2:
            modes = ba.Lstr(value='${A}, ${B}',
                            subs=[('${A}', modes_l[0]), ('${B}', modes_l[1])])
        elif len(modes_l) == 1:
            modes = modes_l[0]
        else:
            raise Exception()
        desc = gametype.get_description_display_string(ba.CoopSession)
        tex_name = item_info['previewTex']
        base_text_scale = 0.8
        title_v = 0.48
        price_v = 0.17

    elif item_name.startswith('icons.'):
        base_text_scale = 1.5
        price_v = 0.2
        check_pos = 0.6

    if item_name.startswith('characters.'):
        frame_size = b_width * 0.7
        im_dim = frame_size * (100.0 / 113.0)
        im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x,
                  b_pos[1] + b_height * 0.57 - im_dim * 0.5)
        mask_texture = ba.gettexture('characterIconMask')
        assert icon_tex is not None
        assert tint_tex is not None
        ba.imagewidget(parent=parent_widget,
                       position=im_pos,
                       size=(im_dim, im_dim),
                       color=(1, 1, 1),
                       transition_delay=delay,
                       mask_texture=mask_texture,
                       draw_controller=btn,
                       texture=ba.gettexture(icon_tex),
                       tint_texture=ba.gettexture(tint_tex),
                       tint_color=tint_color,
                       tint2_color=tint2_color)

    if item_name in ['pro', 'upgrades.pro']:
        frame_size = b_width * 0.5
        im_dim = frame_size * (100.0 / 113.0)
        im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x,
                  b_pos[1] + b_height * 0.5 - im_dim * 0.5)
        ba.imagewidget(parent=parent_widget,
                       position=im_pos,
                       size=(im_dim, im_dim),
                       transition_delay=delay,
                       draw_controller=btn,
                       color=(0.3, 0.0, 0.3),
                       opacity=0.3,
                       texture=ba.gettexture('logo'))
        txt = ba.Lstr(resource='store.bombSquadProNewDescriptionText')

        # t = 'foo\nfoo\nfoo\nfoo\nfoo\nfoo'
        item['descriptionText'] = ba.textwidget(
            parent=parent_widget,
            text=txt,
            position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.69),
            transition_delay=delay,
            scale=b_width * (1.0 / 230.0) * base_text_scale * 0.75,
            maxwidth=b_width * 0.75,
            max_height=b_height * 0.2,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=btn,
            color=(0.3, 1, 0.3))

        extra_backings = item['extra_backings'] = []
        extra_images = item['extra_images'] = []
        extra_texts = item['extra_texts'] = []
        extra_texts_2 = item['extra_texts_2'] = []

        backing_color = (0.5, 0.8, 0.3) if button else (0.6, 0.5, 0.65)
        b_square_texture = ba.gettexture('buttonSquare')
        char_mask_texture = ba.gettexture('characterIconMask')

        pos = (0.17, 0.43)
        tile_size = (b_width * 0.16 * 1.2, b_width * 0.2 * 1.2)
        tile_pos = (b_pos[0] + b_width * pos[0], b_pos[1] + b_height * pos[1])
        extra_backings.append(
            ba.imagewidget(parent=parent_widget,
                           position=(tile_pos[0] - tile_size[0] * 0.5,
                                     tile_pos[1] - tile_size[1] * 0.5),
                           size=tile_size,
                           transition_delay=delay,
                           draw_controller=btn,
                           color=backing_color,
                           texture=b_square_texture))
        im_size = tile_size[0] * 0.8
        extra_images.append(
            ba.imagewidget(parent=parent_widget,
                           position=(tile_pos[0] - im_size * 0.5,
                                     tile_pos[1] - im_size * 0.4),
                           size=(im_size, im_size),
                           transition_delay=delay,
                           draw_controller=btn,
                           color=(1, 1, 1),
                           texture=ba.gettexture('ticketsMore')))
        bonus_tickets = str(
            _ba.get_v1_account_misc_read_val('proBonusTickets', 100))
        extra_texts.append(
            ba.textwidget(parent=parent_widget,
                          draw_controller=btn,
                          position=(tile_pos[0] - tile_size[0] * 0.03,
                                    tile_pos[1] - tile_size[1] * 0.25),
                          size=(0, 0),
                          color=(0.6, 1, 0.6),
                          transition_delay=delay,
                          h_align='center',
                          v_align='center',
                          maxwidth=tile_size[0] * 0.7,
                          scale=0.55,
                          text=ba.Lstr(resource='getTicketsWindow.ticketsText',
                                       subs=[('${COUNT}', bonus_tickets)]),
                          flatness=1.0,
                          shadow=0.0))

        for charname, pos in [('Kronk', (0.32, 0.45)), ('Zoe', (0.425, 0.4)),
                              ('Jack Morgan', (0.555, 0.45)),
                              ('Mel', (0.645, 0.4))]:
            tile_size = (b_width * 0.16 * 0.9, b_width * 0.2 * 0.9)
            tile_pos = (b_pos[0] + b_width * pos[0],
                        b_pos[1] + b_height * pos[1])
            character = ba.app.spaz_appearances[charname]
            extra_backings.append(
                ba.imagewidget(parent=parent_widget,
                               position=(tile_pos[0] - tile_size[0] * 0.5,
                                         tile_pos[1] - tile_size[1] * 0.5),
                               size=tile_size,
                               transition_delay=delay,
                               draw_controller=btn,
                               color=backing_color,
                               texture=b_square_texture))
            im_size = tile_size[0] * 0.7
            extra_images.append(
                ba.imagewidget(parent=parent_widget,
                               position=(tile_pos[0] - im_size * 0.53,
                                         tile_pos[1] - im_size * 0.35),
                               size=(im_size, im_size),
                               transition_delay=delay,
                               draw_controller=btn,
                               color=(1, 1, 1),
                               texture=ba.gettexture(character.icon_texture),
                               tint_texture=ba.gettexture(
                                   character.icon_mask_texture),
                               tint_color=character.default_color,
                               tint2_color=character.default_highlight,
                               mask_texture=char_mask_texture))
            extra_texts.append(
                ba.textwidget(parent=parent_widget,
                              draw_controller=btn,
                              position=(tile_pos[0] - im_size * 0.03,
                                        tile_pos[1] - im_size * 0.51),
                              size=(0, 0),
                              color=(0.6, 1, 0.6),
                              transition_delay=delay,
                              h_align='center',
                              v_align='center',
                              maxwidth=tile_size[0] * 0.7,
                              scale=0.55,
                              text=ba.Lstr(translate=('characterNames',
                                                      charname)),
                              flatness=1.0,
                              shadow=0.0))

        # If we have a 'total-worth' item-id for this id, show that price so
        # the user knows how much this is worth.
        total_worth_item = _ba.get_v1_account_misc_read_val('twrths',
                                                            {}).get(item_name)
        total_worth_price: Optional[str]
        if total_worth_item is not None:
            price = _ba.get_price(total_worth_item)
            total_worth_price = (get_clean_price(price)
                                 if price is not None else '??')
        else:
            total_worth_price = None

        if total_worth_price is not None:
            total_worth_text = ba.Lstr(resource='store.totalWorthText',
                                       subs=[('${TOTAL_WORTH}',
                                              total_worth_price)])
            extra_texts_2.append(
                ba.textwidget(parent=parent_widget,
                              text=total_worth_text,
                              position=(b_pos[0] + b_width * 0.5 + b_offs_x,
                                        b_pos[1] + b_height * 0.25),
                              transition_delay=delay,
                              scale=b_width * (1.0 / 230.0) * base_text_scale *
                              0.45,
                              maxwidth=b_width * 0.5,
                              size=(0, 0),
                              h_align='center',
                              v_align='center',
                              shadow=1.0,
                              flatness=1.0,
                              draw_controller=btn,
                              color=(0.3, 1, 1)))

        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')
        mask_tex = ba.gettexture('mapPreviewMask')
        for levelname, preview_tex_name, pos in [
            ('Infinite Onslaught', 'doomShroomPreview', (0.80, 0.48)),
            ('Infinite Runaround', 'towerDPreview', (0.80, 0.32))
        ]:
            tile_size = (b_width * 0.2, b_width * 0.13)
            tile_pos = (b_pos[0] + b_width * pos[0],
                        b_pos[1] + b_height * pos[1])
            im_size = tile_size[0] * 0.8
            extra_backings.append(
                ba.imagewidget(parent=parent_widget,
                               position=(tile_pos[0] - tile_size[0] * 0.5,
                                         tile_pos[1] - tile_size[1] * 0.5),
                               size=tile_size,
                               transition_delay=delay,
                               draw_controller=btn,
                               color=backing_color,
                               texture=b_square_texture))

            # Hack - gotta draw two transparent versions to avoid z issues.
            for mod in model_opaque, model_transparent:
                extra_images.append(
                    ba.imagewidget(parent=parent_widget,
                                   position=(tile_pos[0] - im_size * 0.52,
                                             tile_pos[1] - im_size * 0.2),
                                   size=(im_size, im_size * 0.5),
                                   transition_delay=delay,
                                   model_transparent=mod,
                                   mask_texture=mask_tex,
                                   draw_controller=btn,
                                   texture=ba.gettexture(preview_tex_name)))

            extra_texts.append(
                ba.textwidget(parent=parent_widget,
                              draw_controller=btn,
                              position=(tile_pos[0] - im_size * 0.03,
                                        tile_pos[1] - im_size * 0.2),
                              size=(0, 0),
                              color=(0.6, 1, 0.6),
                              transition_delay=delay,
                              h_align='center',
                              v_align='center',
                              maxwidth=tile_size[0] * 0.7,
                              scale=0.55,
                              text=ba.Lstr(translate=('coopLevelNames',
                                                      levelname)),
                              flatness=1.0,
                              shadow=0.0))

    if item_name.startswith('icons.'):
        item['icon_text'] = ba.textwidget(
            parent=parent_widget,
            text=item_info['icon'],
            position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.5),
            transition_delay=delay,
            scale=b_width * (1.0 / 230.0) * base_text_scale * 2.0,
            maxwidth=b_width * 0.9,
            max_height=b_height * 0.9,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=btn)

    if item_name.startswith('maps.'):
        frame_size = b_width * 0.9
        im_dim = frame_size * (100.0 / 113.0)
        im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x,
                  b_pos[1] + b_height * 0.62 - im_dim * 0.25)
        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')
        mask_tex = ba.gettexture('mapPreviewMask')
        assert tex_name is not None
        ba.imagewidget(parent=parent_widget,
                       position=im_pos,
                       size=(im_dim, im_dim * 0.5),
                       transition_delay=delay,
                       model_opaque=model_opaque,
                       model_transparent=model_transparent,
                       mask_texture=mask_tex,
                       draw_controller=btn,
                       texture=ba.gettexture(tex_name))

    if item_name.startswith('games.'):
        frame_size = b_width * 0.8
        im_dim = frame_size * (100.0 / 113.0)
        im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x,
                  b_pos[1] + b_height * 0.72 - im_dim * 0.25)
        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')
        mask_tex = ba.gettexture('mapPreviewMask')
        assert tex_name is not None
        ba.imagewidget(parent=parent_widget,
                       position=im_pos,
                       size=(im_dim, im_dim * 0.5),
                       transition_delay=delay,
                       model_opaque=model_opaque,
                       model_transparent=model_transparent,
                       mask_texture=mask_tex,
                       draw_controller=btn,
                       texture=ba.gettexture(tex_name))
        item['descriptionText'] = ba.textwidget(
            parent=parent_widget,
            text=desc,
            position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.36),
            transition_delay=delay,
            scale=b_width * (1.0 / 230.0) * base_text_scale * 0.78,
            maxwidth=b_width * 0.8,
            max_height=b_height * 0.14,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=btn,
            flatness=1.0,
            shadow=0.0,
            color=(0.6, 1, 0.6))
        item['gameModesText'] = ba.textwidget(
            parent=parent_widget,
            text=modes,
            position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.26),
            transition_delay=delay,
            scale=b_width * (1.0 / 230.0) * base_text_scale * 0.65,
            maxwidth=b_width * 0.8,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=btn,
            shadow=0,
            flatness=1.0,
            color=(0.6, 0.8, 0.6))

    if not item_name.startswith('icons.'):
        item['title_text'] = ba.textwidget(
            parent=parent_widget,
            text=title,
            position=(b_pos[0] + b_width * 0.5 + b_offs_x,
                      b_pos[1] + b_height * title_v),
            transition_delay=delay,
            scale=b_width * (1.0 / 230.0) * base_text_scale,
            maxwidth=b_width * 0.8,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=btn,
            color=(0.7, 0.9, 0.7, 1.0))

    item['purchase_check'] = ba.imagewidget(
        parent=parent_widget,
        position=(b_pos[0] + b_width * check_pos, b_pos[1] + b_height * 0.05),
        transition_delay=delay,
        model_transparent=ba.getmodel('checkTransparent'),
        opacity=0.0,
        size=(60, 60),
        color=(0.6, 0.5, 0.8),
        draw_controller=btn,
        texture=ba.gettexture('uiAtlas'))
    item['price_widget'] = ba.textwidget(
        parent=parent_widget,
        text='',
        position=(b_pos[0] + b_width * 0.5 + b_offs_x,
                  b_pos[1] + b_height * price_v),
        transition_delay=delay,
        scale=b_width * (1.0 / 300.0) * base_text_scale,
        maxwidth=b_width * 0.9,
        size=(0, 0),
        h_align='center',
        v_align='center',
        draw_controller=btn,
        color=(0.2, 1, 0.2, 1.0))
    item['price_widget_left'] = ba.textwidget(
        parent=parent_widget,
        text='',
        position=(b_pos[0] + b_width * 0.33 + b_offs_x,
                  b_pos[1] + b_height * price_v),
        transition_delay=delay,
        scale=b_width * (1.0 / 300.0) * base_text_scale,
        maxwidth=b_width * 0.3,
        size=(0, 0),
        h_align='center',
        v_align='center',
        draw_controller=btn,
        color=(0.2, 1, 0.2, 0.5))
    item['price_widget_right'] = ba.textwidget(
        parent=parent_widget,
        text='',
        position=(b_pos[0] + b_width * 0.66 + b_offs_x,
                  b_pos[1] + b_height * price_v),
        transition_delay=delay,
        scale=1.1 * b_width * (1.0 / 300.0) * base_text_scale,
        maxwidth=b_width * 0.3,
        size=(0, 0),
        h_align='center',
        v_align='center',
        draw_controller=btn,
        color=(0.2, 1, 0.2, 1.0))
    item['price_slash_widget'] = ba.imagewidget(
        parent=parent_widget,
        position=(b_pos[0] + b_width * 0.33 + b_offs_x - 36,
                  b_pos[1] + b_height * price_v - 35),
        transition_delay=delay,
        texture=ba.gettexture('slash'),
        opacity=0.0,
        size=(70, 70),
        draw_controller=btn,
        color=(1, 0, 0))
    badge_rad = 44
    badge_center = (b_pos[0] + b_width * 0.1 + b_offs_x,
                    b_pos[1] + b_height * 0.87)
    item['sale_bg_widget'] = ba.imagewidget(
        parent=parent_widget,
        position=(badge_center[0] - badge_rad, badge_center[1] - badge_rad),
        opacity=0.0,
        transition_delay=delay,
        texture=ba.gettexture('circleZigZag'),
        draw_controller=btn,
        size=(badge_rad * 2, badge_rad * 2),
        color=(0.5, 0, 1))
    item['sale_title_widget'] = ba.textwidget(parent=parent_widget,
                                              position=(badge_center[0],
                                                        badge_center[1] + 12),
                                              transition_delay=delay,
                                              scale=1.0,
                                              maxwidth=badge_rad * 1.6,
                                              size=(0, 0),
                                              h_align='center',
                                              v_align='center',
                                              draw_controller=btn,
                                              shadow=0.0,
                                              flatness=1.0,
                                              color=(0, 1, 0))
    item['sale_time_widget'] = ba.textwidget(parent=parent_widget,
                                             position=(badge_center[0],
                                                       badge_center[1] - 12),
                                             transition_delay=delay,
                                             scale=0.7,
                                             maxwidth=badge_rad * 1.6,
                                             size=(0, 0),
                                             h_align='center',
                                             v_align='center',
                                             draw_controller=btn,
                                             shadow=0.0,
                                             flatness=1.0,
                                             color=(0.0, 1, 0.0, 1))
Beispiel #28
0
 def __init__(self, origin_widget: ba.Widget = None):
     scale_origin: Optional[tuple[float, float]]
     if origin_widget is not None:
         self._transition_out = 'out_scale'
         scale_origin = origin_widget.get_screen_space_center()
         transition = 'in_scale'
     else:
         self._transition_out = 'out_right'
         scale_origin = None
         transition = 'in_right'
     bg_color = (0.4, 0.4, 0.5)
     self._width = 560
     self._height = 420
     uiscale = ba.app.ui.uiscale
     base_scale = (1.65 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.1)
     super().__init__(root_widget=ba.containerwidget(
         size=(self._width, self._height),
         transition=transition,
         scale=base_scale,
         scale_origin_stack_offset=scale_origin,
         stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0)))
     self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                           position=(40, self._height - 45),
                                           size=(50, 50),
                                           scale=0.7,
                                           label='',
                                           color=bg_color,
                                           on_activate_call=self._cancel,
                                           autoselect=True,
                                           icon=ba.gettexture('crossOut'),
                                           iconscale=1.2)
     maxlinks = _ba.get_v1_account_misc_read_val('maxLinkAccounts', 5)
     ba.textwidget(
         parent=self._root_widget,
         position=(self._width * 0.5, self._height * 0.56),
         size=(0, 0),
         text=ba.Lstr(resource=(
             'accountSettingsWindow.linkAccountsInstructionsNewText'),
                      subs=[('${COUNT}', str(maxlinks))]),
         maxwidth=self._width * 0.9,
         color=ba.app.ui.infotextcolor,
         max_height=self._height * 0.6,
         h_align='center',
         v_align='center')
     ba.containerwidget(edit=self._root_widget,
                        cancel_button=self._cancel_button)
     ba.buttonwidget(
         parent=self._root_widget,
         position=(40, 30),
         size=(200, 60),
         label=ba.Lstr(
             resource='accountSettingsWindow.linkAccountsGenerateCodeText'),
         autoselect=True,
         on_activate_call=self._generate_press)
     self._enter_code_button = ba.buttonwidget(
         parent=self._root_widget,
         position=(self._width - 240, 30),
         size=(200, 60),
         label=ba.Lstr(
             resource='accountSettingsWindow.linkAccountsEnterCodeText'),
         autoselect=True,
         on_activate_call=self._enter_code_press)
Beispiel #29
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 origin_widget: ba.Widget = None,
                 close_once_signed_in: bool = False):
        # pylint: disable=too-many-statements

        self._sign_in_game_circle_button: Optional[ba.Widget] = None
        self._sign_in_v2_button: Optional[ba.Widget] = None
        self._sign_in_device_button: Optional[ba.Widget] = None

        self._close_once_signed_in = close_once_signed_in
        ba.set_analytics_screen('Account Window')

        # If they provided an origin-widget, scale up from that.
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'accountSettingsWindow'
        self._modal = modal
        self._needs_refresh = False
        self._signed_in = (_ba.get_v1_account_state() == 'signed_in')
        self._account_state_num = _ba.get_v1_account_state_num()
        self._show_linked = (self._signed_in
                             and _ba.get_v1_account_misc_read_val(
                                 'allowAccountLinking2', False))
        self._check_sign_in_timer = ba.Timer(1.0,
                                             ba.WeakCall(self._update),
                                             timetype=ba.TimeType.REAL,
                                             repeat=True)

        # Currently we can only reset achievements on game-center.
        account_type: Optional[str]
        if self._signed_in:
            account_type = _ba.get_v1_account_type()
        else:
            account_type = None
        self._can_reset_achievements = (account_type == 'Game Center')

        app = ba.app
        uiscale = app.ui.uiscale

        self._width = 760 if uiscale is ba.UIScale.SMALL else 660
        x_offs = 50 if uiscale is ba.UIScale.SMALL else 0
        self._height = (390 if uiscale is ba.UIScale.SMALL else
                        430 if uiscale is ba.UIScale.MEDIUM else 490)

        self._sign_in_button = None
        self._sign_in_text = None

        self._scroll_width = self._width - (100 + x_offs * 2)
        self._scroll_height = self._height - 120
        self._sub_width = self._scroll_width - 20

        # Determine which sign-in/sign-out buttons we should show.
        self._show_sign_in_buttons: list[str] = []

        if app.platform == 'android' and app.subplatform == 'google':
            self._show_sign_in_buttons.append('Google Play')

        elif app.platform == 'android' and app.subplatform == 'amazon':
            self._show_sign_in_buttons.append('Game Circle')

        # Local accounts are generally always available with a few key
        # exceptions.
        self._show_sign_in_buttons.append('Local')

        # Ditto with shiny new V2 ones.
        if bool(True):
            self._show_sign_in_buttons.append('V2')

        top_extra = 15 if uiscale is ba.UIScale.SMALL else 0
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(2.09 if uiscale is ba.UIScale.SMALL else
                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -19) if uiscale is ba.UIScale.SMALL else (0, 0)))
        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            self._back_button = None
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(51 + x_offs, self._height - 62),
                size=(120, 60),
                scale=0.8,
                text_scale=1.2,
                autoselect=True,
                label=ba.Lstr(
                    resource='doneText' if self._modal else 'backText'),
                button_type='regular' if self._modal else 'back',
                on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
            if not self._modal:
                ba.buttonwidget(edit=btn,
                                button_type='backSmall',
                                size=(60, 56),
                                label=ba.charstr(ba.SpecialChar.BACK))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 41),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.ui.title_color,
                      maxwidth=self._width - 340,
                      h_align='center',
                      v_align='center')

        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            highlight=False,
            position=((self._width - self._scroll_width) * 0.5,
                      self._height - 65 - self._scroll_height),
            size=(self._scroll_width, self._scroll_height),
            claims_left_right=True,
            claims_tab=True,
            selection_loops_to_parent=True)
        self._subcontainer: Optional[ba.Widget] = None
        self._refresh()
        self._restore_state()
Beispiel #30
0
    def call_after_ad(self, call: Callable[[], Any]) -> None:
        """Run a call after potentially showing an ad."""
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba._generated.enums import TimeType
        app = _ba.app
        show = True

        # No ads without net-connections, etc.
        if not _ba.can_show_ad():
            show = False
        if app.accounts_v1.have_pro():
            show = False  # Pro disables interstitials.
        try:
            session = _ba.get_foreground_host_session()
            assert session is not None
            is_tournament = session.tournament_id is not None
        except Exception:
            is_tournament = False
        if is_tournament:
            show = False  # Never show ads during tournaments.

        if show:
            interval: Optional[float]
            launch_count = app.config.get('launchCount', 0)

            # If we're seeing short ads we may want to space them differently.
            interval_mult = (_ba.get_v1_account_misc_read_val(
                'ads.shortIntervalMult', 1.0)
                             if self.last_ad_was_short else 1.0)
            if self.ad_amt is None:
                if launch_count <= 1:
                    self.ad_amt = _ba.get_v1_account_misc_read_val(
                        'ads.startVal1', 0.99)
                else:
                    self.ad_amt = _ba.get_v1_account_misc_read_val(
                        'ads.startVal2', 1.0)
                interval = None
            else:
                # So far we're cleared to show; now calc our
                # ad-show-threshold and see if we should *actually* show
                # (we reach our threshold faster the longer we've been
                # playing).
                base = 'ads' if _ba.has_video_ads() else 'ads2'
                min_lc = _ba.get_v1_account_misc_read_val(base + '.minLC', 0.0)
                max_lc = _ba.get_v1_account_misc_read_val(base + '.maxLC', 5.0)
                min_lc_scale = (_ba.get_v1_account_misc_read_val(
                    base + '.minLCScale', 0.25))
                max_lc_scale = (_ba.get_v1_account_misc_read_val(
                    base + '.maxLCScale', 0.34))
                min_lc_interval = (_ba.get_v1_account_misc_read_val(
                    base + '.minLCInterval', 360))
                max_lc_interval = (_ba.get_v1_account_misc_read_val(
                    base + '.maxLCInterval', 300))
                if launch_count < min_lc:
                    lc_amt = 0.0
                elif launch_count > max_lc:
                    lc_amt = 1.0
                else:
                    lc_amt = ((float(launch_count) - min_lc) /
                              (max_lc - min_lc))
                incr = (1.0 - lc_amt) * min_lc_scale + lc_amt * max_lc_scale
                interval = ((1.0 - lc_amt) * min_lc_interval +
                            lc_amt * max_lc_interval)
                self.ad_amt += incr
            assert self.ad_amt is not None
            if self.ad_amt >= 1.0:
                self.ad_amt = self.ad_amt % 1.0
                self.attempted_first_ad = True

            # After we've reached the traditional show-threshold once,
            # try again whenever its been INTERVAL since our last successful
            # show.
            elif (
                    self.attempted_first_ad and
                (self.last_ad_completion_time is None or
                 (interval is not None
                  and _ba.time(TimeType.REAL) - self.last_ad_completion_time >
                  (interval * interval_mult)))):
                # Reset our other counter too in this case.
                self.ad_amt = 0.0
            else:
                show = False

        # If we're *still* cleared to show, actually tell the system to show.
        if show:
            # As a safety-check, set up an object that will run
            # the completion callback if we've returned and sat for 10 seconds
            # (in case some random ad network doesn't properly deliver its
            # completion callback).
            class _Payload:
                def __init__(self, pcall: Callable[[], Any]):
                    self._call = pcall
                    self._ran = False

                def run(self, fallback: bool = False) -> None:
                    """Run fallback call (and issue a warning about it)."""
                    if not self._ran:
                        if fallback:
                            print(
                                ('ERROR: relying on fallback ad-callback! '
                                 'last network: ' + app.ads.last_ad_network +
                                 ' (set ' + str(
                                     int(time.time() -
                                         app.ads.last_ad_network_set_time)) +
                                 's ago); purpose=' + app.ads.last_ad_purpose))
                        _ba.pushcall(self._call)
                        self._ran = True

            payload = _Payload(call)
            with _ba.Context('ui'):
                _ba.timer(5.0,
                          lambda: payload.run(fallback=True),
                          timetype=TimeType.REAL)
            self.show_ad('between_game', on_completion_call=payload.run)
        else:
            _ba.pushcall(call)  # Just run the callback without the ad.