예제 #1
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_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))
예제 #2
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_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)
예제 #3
0
 def _on_pro_mult_press(self) -> None:
     from bastd.ui import confirm
     txt = ba.Lstr(
         resource='coopSelectWindow.proMultInfoText',
         subs=[
             ('${PERCENT}',
              str(_ba.get_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)
예제 #4
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_account_misc_read_val('pubPartyRefreshMS', 10000)):
            self._last_server_list_query_time = now
            if DEBUG_SERVER_COMMUNICATION:
                print('REQUESTING SERVER LIST')
            _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()
예제 #5
0
 def _get_custom_logo_tex_name(self) -> Optional[str]:
     if _ba.get_account_misc_read_val('easter', False):
         return 'logoEaster'
     return None
예제 #6
0
    def __init__(self, offer: Dict[str, Any], transition: str = 'in_right'):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import (get_store_item_display_size, get_clean_price)
        from ba import SpecialChar
        from bastd.ui.store import item as storeitemui
        self._cancel_delay = offer.get('cancelDelay', 0)

        # First thing: if we're offering pro or an IAP, see if we have a
        # price for it.
        # If not, abort and go into zombie mode (the user should never see
        # us that way).

        real_price: Optional[str]

        # Misnomer: 'pro' actually means offer 'pro_sale'.
        if offer['item'] in ['pro', 'pro_fullprice']:
            real_price = _ba.get_price('pro' if offer['item'] ==
                                       'pro_fullprice' else 'pro_sale')
            if real_price is None and ba.app.debug_build:
                print('NOTE: Faking prices for debug build.')
                real_price = '$1.23'
            zombie = real_price is None
        elif isinstance(offer['price'], str):
            # (a string price implies IAP id)
            real_price = _ba.get_price(offer['price'])
            if real_price is None and ba.app.debug_build:
                print('NOTE: Faking price for debug build.')
                real_price = '$1.23'
            zombie = real_price is None
        else:
            real_price = None
            zombie = False
        if real_price is None:
            real_price = '?'

        if offer['item'] in ['pro', 'pro_fullprice']:
            self._offer_item = 'pro'
        else:
            self._offer_item = offer['item']

        # If we wanted a real price but didn't find one, go zombie.
        if zombie:
            return

        # This can pop up suddenly, so lets block input for 1 second.
        _ba.lock_all_input()
        ba.timer(1.0, _ba.unlock_all_input, timetype=ba.TimeType.REAL)
        ba.playsound(ba.getsound('ding'))
        ba.timer(0.3,
                 lambda: ba.playsound(ba.getsound('ooh')),
                 timetype=ba.TimeType.REAL)
        self._offer = copy.deepcopy(offer)
        self._width = 580
        self._height = 590
        uiscale = ba.app.ui.uiscale
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            scale=(1.2 if uiscale is ba.UIScale.SMALL else
                   1.15 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -15) if uiscale is ba.UIScale.SMALL else (0, 0)))
        self._is_bundle_sale = False
        try:
            if offer['item'] in ['pro', 'pro_fullprice']:
                original_price_str = _ba.get_price('pro')
                if original_price_str is None:
                    original_price_str = '?'
                new_price_str = _ba.get_price('pro_sale')
                if new_price_str is None:
                    new_price_str = '?'
                percent_off_text = ''
            else:
                # If the offer includes bonus tickets, it's a bundle-sale.
                if ('bonusTickets' in offer
                        and offer['bonusTickets'] is not None):
                    self._is_bundle_sale = True
                original_price = _ba.get_account_misc_read_val(
                    'price.' + self._offer_item, 9999)

                # For pure ticket prices we can show a percent-off.
                if isinstance(offer['price'], int):
                    new_price = offer['price']
                    tchar = ba.charstr(SpecialChar.TICKET)
                    original_price_str = tchar + str(original_price)
                    new_price_str = tchar + str(new_price)
                    percent_off = int(
                        round(100.0 -
                              (float(new_price) / original_price) * 100.0))
                    percent_off_text = ' ' + ba.Lstr(
                        resource='store.salePercentText').evaluate().replace(
                            '${PERCENT}', str(percent_off))
                else:
                    original_price_str = new_price_str = '?'
                    percent_off_text = ''

        except Exception:
            print(f'Offer: {offer}')
            ba.print_exception('Error setting up special-offer')
            original_price_str = new_price_str = '?'
            percent_off_text = ''

        # If its a bundle sale, change the title.
        if self._is_bundle_sale:
            sale_text = ba.Lstr(resource='store.saleBundleText',
                                fallback_resource='store.saleText').evaluate()
        else:
            # For full pro we say 'Upgrade?' since its not really a sale.
            if offer['item'] == 'pro_fullprice':
                sale_text = ba.Lstr(
                    resource='store.upgradeQuestionText',
                    fallback_resource='store.saleExclaimText').evaluate()
            else:
                sale_text = ba.Lstr(
                    resource='store.saleExclaimText',
                    fallback_resource='store.saleText').evaluate()

        self._title_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height - 40),
            size=(0, 0),
            text=sale_text +
            ((' ' + ba.Lstr(resource='store.oneTimeOnlyText').evaluate())
             if self._offer['oneTimeOnly'] else '') + percent_off_text,
            h_align='center',
            v_align='center',
            maxwidth=self._width * 0.9 - 220,
            scale=1.4,
            color=(0.3, 1, 0.3))

        self._flash_on = False
        self._flashing_timer: Optional[ba.Timer] = ba.Timer(
            0.05,
            ba.WeakCall(self._flash_cycle),
            repeat=True,
            timetype=ba.TimeType.REAL)
        ba.timer(0.6,
                 ba.WeakCall(self._stop_flashing),
                 timetype=ba.TimeType.REAL)

        size = get_store_item_display_size(self._offer_item)
        display: Dict[str, Any] = {}
        storeitemui.instantiate_store_item_display(
            self._offer_item,
            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_bundle_sale else 0),
                   self._height * 0.5 - size[1] * 0.5 + 20 +
                   (20 if self._is_bundle_sale else 0)),
            b_width=size[0],
            b_height=size[1],
            button=not self._is_bundle_sale)

        # Wire up the parts we need.
        if self._is_bundle_sale:
            self._plus_text = ba.textwidget(parent=self._root_widget,
                                            position=(self._width * 0.5,
                                                      self._height * 0.5 + 50),
                                            size=(0, 0),
                                            text='+',
                                            h_align='center',
                                            v_align='center',
                                            maxwidth=self._width * 0.9,
                                            scale=1.4,
                                            color=(0.5, 0.5, 0.5))
            self._plus_tickets = ba.textwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 + 120, self._height * 0.5 + 50),
                size=(0, 0),
                text=ba.charstr(SpecialChar.TICKET_BACKING) +
                str(offer['bonusTickets']),
                h_align='center',
                v_align='center',
                maxwidth=self._width * 0.9,
                scale=2.5,
                color=(0.2, 1, 0.2))
            self._price_text = ba.textwidget(parent=self._root_widget,
                                             position=(self._width * 0.5, 150),
                                             size=(0, 0),
                                             text=real_price,
                                             h_align='center',
                                             v_align='center',
                                             maxwidth=self._width * 0.9,
                                             scale=1.4,
                                             color=(0.2, 1, 0.2))
            # Total-value if they supplied it.
            total_worth_item = offer.get('valueItem', None)
            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 None)
                if total_worth_price is not None:
                    total_worth_text = ba.Lstr(resource='store.totalWorthText',
                                               subs=[('${TOTAL_WORTH}',
                                                      total_worth_price)])
                    self._total_worth_text = ba.textwidget(
                        parent=self._root_widget,
                        text=total_worth_text,
                        position=(self._width * 0.5, 210),
                        scale=0.9,
                        maxwidth=self._width * 0.7,
                        size=(0, 0),
                        h_align='center',
                        v_align='center',
                        shadow=1.0,
                        flatness=1.0,
                        color=(0.3, 1, 1))

        elif offer['item'] == 'pro_fullprice':
            # for full-price pro we simply show full price
            ba.textwidget(edit=display['price_widget'], text=real_price)
            ba.buttonwidget(edit=display['button'],
                            on_activate_call=self._purchase)
        else:
            # Show old/new prices otherwise (for pro sale).
            ba.buttonwidget(edit=display['button'],
                            on_activate_call=self._purchase)
            ba.imagewidget(edit=display['price_slash_widget'], opacity=1.0)
            ba.textwidget(edit=display['price_widget_left'],
                          text=original_price_str)
            ba.textwidget(edit=display['price_widget_right'],
                          text=new_price_str)

        # Add ticket button only if this is ticket-purchasable.
        if isinstance(offer.get('price'), int):
            self._get_tickets_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(self._width - 125, self._height - 68),
                size=(90, 55),
                scale=1.0,
                button_type='square',
                color=(0.7, 0.5, 0.85),
                textcolor=(0.2, 1, 0.2),
                autoselect=True,
                label=ba.Lstr(resource='getTicketsWindow.titleText'),
                on_activate_call=self._on_get_more_tickets_press)

            self._ticket_text_update_timer = ba.Timer(
                1.0,
                ba.WeakCall(self._update_tickets_text),
                timetype=ba.TimeType.REAL,
                repeat=True)
            self._update_tickets_text()

        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) if self._is_bundle_sale else
            (self._width * 0.5 - 75, 40),
            size=(150, 60),
            scale=1.0,
            on_activate_call=self._cancel,
            autoselect=True,
            label=ba.Lstr(resource='noThanksText'))
        self._cancel_countdown_text = ba.textwidget(
            parent=self._root_widget,
            text='',
            position=(50 + 150 + 20, 40 + 27) if self._is_bundle_sale else
            (self._width * 0.5 - 75 + 150 + 20, 40 + 27),
            scale=1.1,
            size=(0, 0),
            h_align='left',
            v_align='center',
            shadow=1.0,
            flatness=1.0,
            color=(0.6, 0.5, 0.5))
        self._update_cancel_button_graphics()

        if self._is_bundle_sale:
            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
                           if self._is_bundle_sale else None,
                           selected_child=self._purchase_button
                           if self._is_bundle_sale else display['button'])
예제 #7
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_account_state()
        account_type = (_ba.get_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_ali_sign_in_button = (account_state == 'signed_out'
                                   and 'Ali' in self._show_sign_in_buttons)
        show_test_sign_in_button = (account_state == 'signed_out'
                                    and 'Test' in self._show_sign_in_buttons)
        show_device_sign_in_button = (account_state == 'signed_out' and 'Local'
                                      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_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', 'Test'))
        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_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 ['Test', 'Local', 'Google Play'])
        sign_out_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_ali_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_test_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_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
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False)
        ba.containerwidget(edit=self._scrollwidget,
                           claims_left_right=True,
                           claims_tab=True,
                           selection_loop_to_parent=True)
        ba.containerwidget(edit=self._subcontainer,
                           claims_left_right=True,
                           claims_tab=True,
                           selection_loop_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_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.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.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.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_ali_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_ali_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.ALIBABA_LOGO)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r + '.signInText'))
                                    ]),
                on_activate_call=lambda: self._sign_in_press('Ali'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.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.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

        # Old test-account option.
        if show_test_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_test_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('Test'))
            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.TEST_ACCOUNT)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithTestAccountText'))]),
                          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 +
                                       '.signInWithTestAccountInfoText'),
                          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.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.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_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 Exception("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.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.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.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.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.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.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.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
예제 #8
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.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_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_account_ticket_count())
        except Exception:
            t_str = '?'
        if self._get_tickets_button is not None:
            ba.buttonwidget(edit=self._get_tickets_button,
                            label=ba.charstr(ba.SpecialChar.TICKET) + t_str)
예제 #9
0
    def _update(self) -> None:
        # pylint: disable=too-many-branches
        from ba import SpecialChar, TimeFormat
        from ba.internal import (get_available_sale_time,
                                 get_available_purchase_count)
        if not self._button:
            return  # Our instance may outlive our UI objects.

        if self._ticket_text is not None:
            if _ba.get_account_state() == 'signed_in':
                sval = ba.charstr(SpecialChar.TICKET) + str(
                    _ba.get_account_ticket_count())
            else:
                sval = '-'
            ba.textwidget(edit=self._ticket_text, text=sval)
        available_purchases = get_available_purchase_count()

        # Old pro sale stuff..
        sale_time = get_available_sale_time('extras')

        # ..also look for new style sales.
        if sale_time is None:
            import datetime
            sales_raw = _ba.get_account_misc_read_val('sales', {})
            sale_times = []
            try:
                # Look at the current set of sales; filter any with time
                # remaining that we don't own.
                for sale_item, sale_info in list(sales_raw.items()):
                    if not _ba.get_purchased(sale_item):
                        to_end = (datetime.datetime.utcfromtimestamp(
                            sale_info['e']) -
                                  datetime.datetime.utcnow()).total_seconds()
                        if to_end > 0:
                            sale_times.append(to_end)
            except Exception:
                ba.print_exception('Error parsing sales')
            if sale_times:
                sale_time = int(min(sale_times) * 1000)

        if sale_time is not None:
            ba.textwidget(edit=self._sale_title_text,
                          text=ba.Lstr(resource='store.saleText'))
            ba.textwidget(edit=self._sale_time_text,
                          text=ba.timestring(
                              sale_time,
                              centi=False,
                              timeformat=TimeFormat.MILLISECONDS))
            ba.imagewidget(edit=self._sale_backing, opacity=1.0)
            ba.imagewidget(edit=self._available_purchase_backing, opacity=1.0)
            ba.textwidget(edit=self._available_purchase_text, text='')
            ba.imagewidget(edit=self._available_purchase_backing, opacity=0.0)
        else:
            ba.imagewidget(edit=self._sale_backing, opacity=0.0)
            ba.textwidget(edit=self._sale_time_text, text='')
            ba.textwidget(edit=self._sale_title_text, text='')
            if available_purchases > 0:
                ba.textwidget(edit=self._available_purchase_text,
                              text=str(available_purchases))
                ba.imagewidget(edit=self._available_purchase_backing,
                               opacity=1.0)
            else:
                ba.textwidget(edit=self._available_purchase_text, text='')
                ba.imagewidget(edit=self._available_purchase_backing,
                               opacity=0.0)
예제 #10
0
    def _refresh_not_in_game(
        self, positions: List[Tuple[float, float,
                                    float]]) -> Tuple[float, float, float]:
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        if not ba.app.did_menu_intro:
            self._tdelay = 2.0
            self._t_delay_inc = 0.02
            self._t_delay_play = 1.7
            ba.app.did_menu_intro = True
        self._width = 400.0
        self._height = 200.0
        enable_account_button = True
        account_type_name: Union[str, ba.Lstr]
        if _ba.get_account_state() == 'signed_in':
            account_type_name = _ba.get_account_display_string()
            account_type_icon = None
            account_textcolor = (1.0, 1.0, 1.0)
        else:
            account_type_name = ba.Lstr(
                resource='notSignedInText',
                fallback_resource='accountSettingsWindow.titleText')
            account_type_icon = None
            account_textcolor = (1.0, 0.2, 0.2)
        account_type_icon_color = (1.0, 1.0, 1.0)
        account_type_call = self._show_account_window
        account_type_enable_button_sound = True
        b_count = 3  # play, help, credits
        if self._have_settings_button:
            b_count += 1
        if enable_account_button:
            b_count += 1
        if self._have_quit_button:
            b_count += 1
        if self._have_store_button:
            b_count += 1
        uiscale = ba.app.ui.uiscale
        if uiscale is ba.UIScale.SMALL:
            root_widget_scale = 1.6
            play_button_width = self._button_width * 0.65
            play_button_height = self._button_height * 1.1
            small_button_scale = 0.51 if b_count > 6 else 0.63
            button_y_offs = -20.0
            button_y_offs2 = -60.0
            self._button_height *= 1.3
            button_spacing = 1.04
        elif uiscale is ba.UIScale.MEDIUM:
            root_widget_scale = 1.3
            play_button_width = self._button_width * 0.65
            play_button_height = self._button_height * 1.1
            small_button_scale = 0.6
            button_y_offs = -55.0
            button_y_offs2 = -75.0
            self._button_height *= 1.25
            button_spacing = 1.1
        else:
            root_widget_scale = 1.0
            play_button_width = self._button_width * 0.65
            play_button_height = self._button_height * 1.1
            small_button_scale = 0.75
            button_y_offs = -80.0
            button_y_offs2 = -100.0
            self._button_height *= 1.2
            button_spacing = 1.1
        spc = self._button_width * small_button_scale * button_spacing
        ba.containerwidget(edit=self._root_widget,
                           size=(self._width, self._height),
                           background=False,
                           scale=root_widget_scale)
        assert not positions
        positions.append((self._width * 0.5, button_y_offs, 1.7))
        x_offs = self._width * 0.5 - (spc * (b_count - 1) * 0.5) + (spc * 0.5)
        for i in range(b_count - 1):
            positions.append(
                (x_offs + spc * i - 1.0, button_y_offs + button_y_offs2,
                 small_button_scale))
        # In kiosk mode, provide a button to get back to the kiosk menu.
        if ba.app.demo_mode or ba.app.arcade_mode:
            h, v, scale = positions[self._p_index]
            this_b_width = self._button_width * 0.4 * scale
            demo_menu_delay = 0.0 if self._t_delay_play == 0.0 else max(
                0, self._t_delay_play + 0.1)
            self._demo_menu_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 - this_b_width * 0.5, v + 90),
                size=(this_b_width, 45),
                autoselect=True,
                color=(0.45, 0.55, 0.45),
                textcolor=(0.7, 0.8, 0.7),
                label=ba.Lstr(resource='modeArcadeText' if ba.app.
                              arcade_mode else 'modeDemoText'),
                transition_delay=demo_menu_delay,
                on_activate_call=self._demo_menu_press)
        else:
            self._demo_menu_button = None
        uiscale = ba.app.ui.uiscale
        foof = (-1 if uiscale is ba.UIScale.SMALL else
                1 if uiscale is ba.UIScale.MEDIUM else 3)
        h, v, scale = positions[self._p_index]
        v = v + foof
        gather_delay = 0.0 if self._t_delay_play == 0.0 else max(
            0.0, self._t_delay_play + 0.1)
        assert play_button_width is not None
        assert play_button_height is not None
        this_h = h - play_button_width * 0.5 * scale - 40 * scale
        this_b_width = self._button_width * 0.25 * scale
        this_b_height = self._button_height * 0.82 * scale
        self._gather_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(this_h - this_b_width * 0.5, v),
            size=(this_b_width, this_b_height),
            autoselect=self._use_autoselect,
            button_type='square',
            label='',
            transition_delay=gather_delay,
            on_activate_call=self._gather_press)
        ba.textwidget(parent=self._root_widget,
                      position=(this_h, v + self._button_height * 0.33),
                      size=(0, 0),
                      scale=0.75,
                      transition_delay=gather_delay,
                      draw_controller=btn,
                      color=(0.75, 1.0, 0.7),
                      maxwidth=self._button_width * 0.33,
                      text=ba.Lstr(resource='gatherWindow.titleText'),
                      h_align='center',
                      v_align='center')
        icon_size = this_b_width * 0.6
        ba.imagewidget(parent=self._root_widget,
                       size=(icon_size, icon_size),
                       draw_controller=btn,
                       transition_delay=gather_delay,
                       position=(this_h - 0.5 * icon_size,
                                 v + 0.31 * this_b_height),
                       texture=ba.gettexture('usersButton'))

        # Play button.
        h, v, scale = positions[self._p_index]
        self._p_index += 1
        self._start_button = start_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h - play_button_width * 0.5 * scale, v),
            size=(play_button_width, play_button_height),
            autoselect=self._use_autoselect,
            scale=scale,
            text_res_scale=2.0,
            label=ba.Lstr(resource='playText'),
            transition_delay=self._t_delay_play,
            on_activate_call=self._play_press)
        ba.containerwidget(edit=self._root_widget,
                           start_button=start_button,
                           selected_child=start_button)
        v = v + foof
        watch_delay = 0.0 if self._t_delay_play == 0.0 else max(
            0.0, self._t_delay_play - 0.1)
        this_h = h + play_button_width * 0.5 * scale + 40 * scale
        this_b_width = self._button_width * 0.25 * scale
        this_b_height = self._button_height * 0.82 * scale
        self._watch_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(this_h - this_b_width * 0.5, v),
            size=(this_b_width, this_b_height),
            autoselect=self._use_autoselect,
            button_type='square',
            label='',
            transition_delay=watch_delay,
            on_activate_call=self._watch_press)
        ba.textwidget(parent=self._root_widget,
                      position=(this_h, v + self._button_height * 0.33),
                      size=(0, 0),
                      scale=0.75,
                      transition_delay=watch_delay,
                      color=(0.75, 1.0, 0.7),
                      draw_controller=btn,
                      maxwidth=self._button_width * 0.33,
                      text=ba.Lstr(resource='watchWindow.titleText'),
                      h_align='center',
                      v_align='center')
        icon_size = this_b_width * 0.55
        ba.imagewidget(parent=self._root_widget,
                       size=(icon_size, icon_size),
                       draw_controller=btn,
                       transition_delay=watch_delay,
                       position=(this_h - 0.5 * icon_size,
                                 v + 0.33 * this_b_height),
                       texture=ba.gettexture('tv'))
        if not self._in_game and enable_account_button:
            this_b_width = self._button_width
            h, v, scale = positions[self._p_index]
            self._p_index += 1
            self._gc_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(h - this_b_width * 0.5 * scale, v),
                size=(this_b_width, self._button_height),
                scale=scale,
                label=account_type_name,
                autoselect=self._use_autoselect,
                on_activate_call=account_type_call,
                textcolor=account_textcolor,
                icon=account_type_icon,
                icon_color=account_type_icon_color,
                transition_delay=self._tdelay,
                enable_sound=account_type_enable_button_sound)

            # Scattered eggs on easter.
            if _ba.get_account_misc_read_val('easter',
                                             False) and not self._in_game:
                icon_size = 32
                ba.imagewidget(parent=self._root_widget,
                               position=(h - icon_size * 0.5 + 35,
                                         v + self._button_height * scale -
                                         icon_size * 0.24 + 1.5),
                               transition_delay=self._tdelay,
                               size=(icon_size, icon_size),
                               texture=ba.gettexture('egg2'),
                               tilt_scale=0.0)
            self._tdelay += self._t_delay_inc
        else:
            self._gc_button = None

        # How-to-play button.
        h, v, scale = positions[self._p_index]
        self._p_index += 1
        btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h - self._button_width * 0.5 * scale, v),
            scale=scale,
            autoselect=self._use_autoselect,
            size=(self._button_width, self._button_height),
            label=ba.Lstr(resource=self._r + '.howToPlayText'),
            transition_delay=self._tdelay,
            on_activate_call=self._howtoplay)
        self._how_to_play_button = btn

        # Scattered eggs on easter.
        if _ba.get_account_misc_read_val('easter',
                                         False) and not self._in_game:
            icon_size = 28
            ba.imagewidget(parent=self._root_widget,
                           position=(h - icon_size * 0.5 + 30,
                                     v + self._button_height * scale -
                                     icon_size * 0.24 + 1.5),
                           transition_delay=self._tdelay,
                           size=(icon_size, icon_size),
                           texture=ba.gettexture('egg4'),
                           tilt_scale=0.0)
        # Credits button.
        self._tdelay += self._t_delay_inc
        h, v, scale = positions[self._p_index]
        self._p_index += 1
        self._credits_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h - self._button_width * 0.5 * scale, v),
            size=(self._button_width, self._button_height),
            autoselect=self._use_autoselect,
            label=ba.Lstr(resource=self._r + '.creditsText'),
            scale=scale,
            transition_delay=self._tdelay,
            on_activate_call=self._credits)
        self._tdelay += self._t_delay_inc
        return h, v, scale
예제 #11
0
def call_after_ad(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._account import have_pro
    from ba._enums import TimeType
    import time
    app = _ba.app
    show = True

    # No ads without net-connections, etc.
    if not _ba.can_show_ad():
        show = False
    if 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_account_misc_read_val(
            'ads.shortIntervalMult', 1.0) if app.last_ad_was_short else 1.0)
        if app.ad_amt is None:
            if launch_count <= 1:
                app.ad_amt = _ba.get_account_misc_read_val(
                    'ads.startVal1', 0.99)
            else:
                app.ad_amt = _ba.get_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_account_misc_read_val(base + '.minLC', 0.0)
            max_lc = _ba.get_account_misc_read_val(base + '.maxLC', 5.0)
            min_lc_scale = (_ba.get_account_misc_read_val(
                base + '.minLCScale', 0.25))
            max_lc_scale = (_ba.get_account_misc_read_val(
                base + '.maxLCScale', 0.34))
            min_lc_interval = (_ba.get_account_misc_read_val(
                base + '.minLCInterval', 360))
            max_lc_interval = (_ba.get_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)
            app.ad_amt += incr
        assert app.ad_amt is not None
        if app.ad_amt >= 1.0:
            app.ad_amt = app.ad_amt % 1.0
            app.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 (app.attempted_first_ad
              and (app.last_ad_completion_time is None or
                   (interval is not None
                    and _ba.time(TimeType.REAL) - app.last_ad_completion_time >
                    (interval * interval_mult)))):
            # Reset our other counter too in this case.
            app.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 the fallback call (and issues a warning about it)."""
                if not self._ran:
                    if fallback:
                        print((
                            'ERROR: relying on fallback ad-callback! '
                            'last network: ' + app.last_ad_network + ' (set ' +
                            str(int(time.time() -
                                    app.last_ad_network_set_time)) +
                            's ago); purpose=' + app.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)
        show_ad('between_game', on_completion_call=payload.run)
    else:
        _ba.pushcall(call)  # Just run the callback without the ad.
예제 #12
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_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))
예제 #13
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_account_misc_read_val('pingGood', 100)
        ping_med = _ba.get_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_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
예제 #14
0
    def _build_server_entry_lines(self, lineheight: float,
                                  ordered_parties: List[PartyEntry],
                                  sub_scroll_height: float,
                                  sub_scroll_width: float) -> None:
        existing_selection = self._selection
        columnwidget = self._join_list_column
        first = True
        assert columnwidget
        for i, party in enumerate(ordered_parties):
            hpos = 20
            vpos = sub_scroll_height - lineheight * i - 50
            party.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(
                    self._set_public_party_selection,
                    Selection(party.index, SelectionComponent.NAME)),
                on_activate_call=ba.WeakCall(self._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=party.name_widget,
                      left_widget=self._join_text,
                      show_buffer_top=64.0,
                      show_buffer_bottom=64.0)
            if existing_selection == Selection(party.index,
                                               SelectionComponent.NAME):
                ba.containerwidget(edit=columnwidget,
                                   selected_child=party.name_widget)
            if party.stats_addr:
                url = party.stats_addr.replace(
                    '${ACCOUNT}',
                    _ba.get_account_misc_read_val_2('resolvedAccountID',
                                                    'UNKNOWN'))
                party.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(
                        self._set_public_party_selection,
                        Selection(party.index,
                                  SelectionComponent.STATS_BUTTON)),
                    size=(120, 40),
                    position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
                    scale=0.9)
                if existing_selection == Selection(
                        party.index, SelectionComponent.STATS_BUTTON):
                    ba.containerwidget(edit=columnwidget,
                                       selected_child=party.stats_button)
            else:
                if party.stats_button:
                    party.stats_button.delete()
                    party.stats_button = None

            if first:
                if party.stats_button:
                    ba.widget(edit=party.stats_button,
                              up_widget=self._filter_text)
                if party.name_widget:
                    ba.widget(edit=party.name_widget,
                              up_widget=self._filter_text)
                first = False

            party.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')
            party.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=party.ping_widget,
                              text='-',
                              color=(0.5, 0.5, 0.5))
            else:
                ping_good = _ba.get_account_misc_read_val('pingGood', 100)
                ping_med = _ba.get_account_misc_read_val('pingMed', 500)
                ba.textwidget(edit=party.ping_widget,
                              text=str(party.ping),
                              color=(0, 1, 0) if party.ping <= ping_good else
                              (1, 1, 0) if party.ping <= ping_med else
                              (1, 0, 0))
예제 #15
0
    def __init__(self) -> None:
        """Instantiate a factory object."""
        # pylint: disable=cyclic-import
        # FIXME: should probably put these somewhere common so we don't
        # have to import them from a module that imports us.
        from bastd.actor.spaz import (PickupMessage, PunchHitMessage,
                                      CurseExplodeMessage)

        shared = SharedObjects.get()
        self.impact_sounds_medium = (ba.getsound('impactMedium'),
                                     ba.getsound('impactMedium2'))
        self.impact_sounds_hard = (ba.getsound('impactHard'),
                                   ba.getsound('impactHard2'),
                                   ba.getsound('impactHard3'))
        self.impact_sounds_harder = (ba.getsound('bigImpact'),
                                     ba.getsound('bigImpact2'))
        self.single_player_death_sound = ba.getsound('playerDeath')
        self.punch_sound = ba.getsound('punch01')
        self.punch_sound_strong = (ba.getsound('punchStrong01'),
                                   ba.getsound('punchStrong02'))
        self.punch_sound_stronger = ba.getsound('superPunch')
        self.swish_sound = ba.getsound('punchSwish')
        self.block_sound = ba.getsound('block')
        self.shatter_sound = ba.getsound('shatter')
        self.splatter_sound = ba.getsound('splatter')
        self.spaz_material = ba.Material()
        self.roller_material = ba.Material()
        self.punch_material = ba.Material()
        self.pickup_material = ba.Material()
        self.curse_material = ba.Material()

        footing_material = shared.footing_material
        object_material = shared.object_material
        player_material = shared.player_material
        region_material = shared.region_material

        # Send footing messages to spazzes so they know when they're on
        # solid ground.
        # Eww; this probably should just be built into the spaz node.
        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))

        # Punches.
        self.punch_material.add_actions(
            conditions=('they_are_different_node_than_us', ),
            actions=(
                ('modify_part_collision', 'collide', True),
                ('modify_part_collision', 'physical', False),
                ('message', 'our_node', 'at_connect', PunchHitMessage()),
            ))

        # Pickups.
        self.pickup_material.add_actions(
            conditions=(('they_are_different_node_than_us', ), 'and',
                        ('they_have_material', object_material)),
            actions=(
                ('modify_part_collision', 'collide', True),
                ('modify_part_collision', 'physical', False),
                ('message', 'our_node', 'at_connect', PickupMessage()),
            ))

        # Curse.
        self.curse_material.add_actions(
            conditions=(
                ('they_are_different_node_than_us', ),
                'and',
                ('they_have_material', player_material),
            ),
            actions=('message', 'our_node', 'at_connect',
                     CurseExplodeMessage()),
        )

        self.foot_impact_sounds = (ba.getsound('footImpact01'),
                                   ba.getsound('footImpact02'),
                                   ba.getsound('footImpact03'))

        self.foot_skid_sound = ba.getsound('skid01')
        self.foot_roll_sound = ba.getsound('scamper01')

        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(
                ('impact_sound', self.foot_impact_sounds, 1, 0.2),
                ('skid_sound', self.foot_skid_sound, 20, 0.3),
                ('roll_sound', self.foot_roll_sound, 20, 3.0),
            ))

        self.skid_sound = ba.getsound('gravelSkid')

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(
                ('impact_sound', self.foot_impact_sounds, 20, 6),
                ('skid_sound', self.skid_sound, 2.0, 1),
                ('roll_sound', self.skid_sound, 2.0, 1),
            ))

        self.shield_up_sound = ba.getsound('shieldUp')
        self.shield_down_sound = ba.getsound('shieldDown')
        self.shield_hit_sound = ba.getsound('shieldHit')

        # We don't want to collide with stuff we're initially overlapping
        # (unless its marked with a special region material).
        self.spaz_material.add_actions(
            conditions=(
                (
                    ('we_are_younger_than', 51),
                    'and',
                    ('they_are_different_node_than_us', ),
                ),
                'and',
                ('they_dont_have_material', region_material),
            ),
            actions=('modify_node_collision', 'collide', False),
        )

        self.spaz_media: dict[str, Any] = {}

        # Lets load some basic rules.
        # (allows them to be tweaked from the master server)
        self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0)
        self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400)
        self.punch_cooldown_gloves = (_ba.get_account_misc_read_val(
            'rpcg', 300))
        self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2)
        self.punch_power_scale_gloves = (_ba.get_account_misc_read_val(
            'rppg', 1.4))
        self.max_shield_spillover_damage = (_ba.get_account_misc_read_val(
            'rsms', 500))
예제 #16
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_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)
예제 #17
0
    def __init__(self) -> None:
        ba.set_analytics_screen('AppInviteWindow')
        self._data: Optional[Dict[str, Any]] = None
        self._width = 650
        self._height = 400

        uiscale = ba.app.uiscale
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition='in_scale',
            scale=(1.8 if uiscale is ba.UIScale.SMALL else
                   1.35 if uiscale is ba.UIScale.MEDIUM else 1.0)))

        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              scale=0.8,
                                              position=(60, self._height - 50),
                                              size=(50, 50),
                                              label='',
                                              on_activate_call=self.close,
                                              autoselect=True,
                                              color=(0.4, 0.4, 0.6),
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)

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

        ba.textwidget(
            parent=self._root_widget,
            size=(0, 0),
            position=(self._width * 0.5, self._height * 0.5 + 110),
            autoselect=True,
            scale=0.8,
            maxwidth=self._width * 0.9,
            h_align='center',
            v_align='center',
            color=(0.3, 0.8, 0.3),
            flatness=1.0,
            text=ba.Lstr(
                resource='gatherWindow.earnTicketsForRecommendingAmountText',
                fallback_resource=(
                    'gatherWindow.earnTicketsForRecommendingText'),
                subs=[
                    ('${COUNT}',
                     str(_ba.get_account_misc_read_val('friendTryTickets',
                                                       300))),
                    ('${YOU_COUNT}',
                     str(
                         _ba.get_account_misc_read_val('friendTryAwardTickets',
                                                       100)))
                ]))

        or_text = ba.Lstr(resource='orText',
                          subs=[('${A}', ''),
                                ('${B}', '')]).evaluate().strip()
        ba.buttonwidget(
            parent=self._root_widget,
            size=(250, 150),
            position=(self._width * 0.5 - 125, self._height * 0.5 - 80),
            autoselect=True,
            button_type='square',
            label=ba.Lstr(resource='gatherWindow.inviteFriendsText'),
            on_activate_call=ba.WeakCall(self._google_invites))

        ba.textwidget(parent=self._root_widget,
                      size=(0, 0),
                      position=(self._width * 0.5, self._height * 0.5 - 94),
                      autoselect=True,
                      scale=0.9,
                      h_align='center',
                      v_align='center',
                      color=(0.5, 0.5, 0.5),
                      flatness=1.0,
                      text=or_text)

        ba.buttonwidget(
            parent=self._root_widget,
            size=(180, 50),
            position=(self._width * 0.5 - 90, self._height * 0.5 - 170),
            autoselect=True,
            color=(0.5, 0.5, 0.6),
            textcolor=(0.7, 0.7, 0.8),
            text_scale=0.8,
            label=ba.Lstr(resource='gatherWindow.appInviteSendACodeText'),
            on_activate_call=ba.WeakCall(self._send_code))

        # kick off a transaction to get our code
        _ba.add_transaction(
            {
                'type': 'FRIEND_PROMO_CODE_REQUEST',
                'ali': False,
                'expire_time': time.time() + 20
            },
            callback=ba.WeakCall(self._on_code_result))
        _ba.run_transactions()
예제 #18
0
 def _get_store_char_tex(self) -> str:
     return ('storeCharacterXmas' if _ba.get_account_misc_read_val(
         'xmas', False) else
             'storeCharacterEaster' if _ba.get_account_misc_read_val(
                 'easter', False) else 'storeCharacter')
예제 #19
0
    def __init__(self) -> None:
        """Instantiate a factory object."""
        self.impact_sounds_medium = (ba.getsound('impactMedium'),
                                     ba.getsound('impactMedium2'))
        self.impact_sounds_hard = (ba.getsound('impactHard'),
                                   ba.getsound('impactHard2'),
                                   ba.getsound('impactHard3'))
        self.impact_sounds_harder = (ba.getsound('bigImpact'),
                                     ba.getsound('bigImpact2'))
        self.single_player_death_sound = ba.getsound('playerDeath')
        self.punch_sound = ba.getsound('punch01')
        self.punch_sound_strong = (ba.getsound('punchStrong01'),
                                   ba.getsound('punchStrong02'))
        self.punch_sound_stronger = ba.getsound('superPunch')
        self.swish_sound = ba.getsound('punchSwish')
        self.block_sound = ba.getsound('block')
        self.shatter_sound = ba.getsound('shatter')
        self.splatter_sound = ba.getsound('splatter')
        self.spaz_material = ba.Material()
        self.roller_material = ba.Material()
        self.punch_material = ba.Material()
        self.pickup_material = ba.Material()
        self.curse_material = ba.Material()

        footing_material = ba.sharedobj('footing_material')
        object_material = ba.sharedobj('object_material')
        player_material = ba.sharedobj('player_material')
        region_material = ba.sharedobj('region_material')

        # send footing messages to spazzes so they know when they're on solid
        # ground.
        # eww this should really just be built into the spaz node
        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('message', 'our_node', 'at_connect', 'footing', 1),
                     ('message', 'our_node', 'at_disconnect', 'footing', -1)))
        # punches
        self.punch_material.add_actions(
            conditions=('they_are_different_node_than_us', ),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('message', 'our_node', 'at_connect',
                      basespaz.PunchHitMessage())))
        # pickups
        self.pickup_material.add_actions(
            conditions=(('they_are_different_node_than_us', ), 'and',
                        ('they_have_material', object_material)),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('message', 'our_node', 'at_connect',
                      basespaz.PickupMessage())))
        # curse
        self.curse_material.add_actions(
            conditions=(('they_are_different_node_than_us', ), 'and',
                        ('they_have_material', player_material)),
            actions=('message', 'our_node', 'at_connect',
                     basespaz.CurseExplodeMessage()))

        self.foot_impact_sounds = (ba.getsound('footImpact01'),
                                   ba.getsound('footImpact02'),
                                   ba.getsound('footImpact03'))

        self.foot_skid_sound = ba.getsound('skid01')
        self.foot_roll_sound = ba.getsound('scamper01')

        self.roller_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('impact_sound', self.foot_impact_sounds, 1,
                      0.2), ('skid_sound', self.foot_skid_sound, 20, 0.3),
                     ('roll_sound', self.foot_roll_sound, 20, 3.0)))

        self.skid_sound = ba.getsound('gravelSkid')

        self.spaz_material.add_actions(
            conditions=('they_have_material', footing_material),
            actions=(('impact_sound', self.foot_impact_sounds, 20,
                      6), ('skid_sound', self.skid_sound, 2.0, 1),
                     ('roll_sound', self.skid_sound, 2.0, 1)))

        self.shield_up_sound = ba.getsound('shieldUp')
        self.shield_down_sound = ba.getsound('shieldDown')
        self.shield_hit_sound = ba.getsound('shieldHit')

        # we don't want to collide with stuff we're initially overlapping
        # (unless its marked with a special region material)
        self.spaz_material.add_actions(
            conditions=((('we_are_younger_than', 51), 'and',
                         ('they_are_different_node_than_us', )), 'and',
                        ('they_dont_have_material', region_material)),
            actions=('modify_node_collision', 'collide', False))

        self.spaz_media: Dict[str, Any] = {}

        # lets load some basic rules (allows them to be tweaked from the
        # master server)
        self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0)
        self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400)
        self.punch_cooldown_gloves = (_ba.get_account_misc_read_val(
            'rpcg', 300))
        self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2)
        self.punch_power_scale_gloves = (_ba.get_account_misc_read_val(
            'rppg', 1.4))
        self.max_shield_spillover_damage = (_ba.get_account_misc_read_val(
            'rsms', 500))
예제 #20
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._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_account_state() == 'signed_in')
        self._account_state_num = _ba.get_account_state_num()
        self._show_linked = (self._signed_in and _ba.get_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_account_type()
        else:
            account_type = None
        self._can_reset_achievements = (account_type == 'Game Center')

        app = ba.app

        self._width = 760 if ba.app.small_ui else 660
        x_offs = 50 if ba.app.small_ui else 0
        self._height = (390
                        if ba.app.small_ui else 430 if ba.app.med_ui 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')

        top_extra = 15 if ba.app.small_ui 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 ba.app.small_ui else 1.4 if ba.app.med_ui else 1.0),
            stack_offset=(0, -19) if ba.app.small_ui else (0, 0)))
        if ba.app.small_ui and ba.app.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.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))
        self._subcontainer: Optional[ba.Widget] = None
        self._refresh()
        self._restore_state()
예제 #21
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
        from ba.internal import get_league_rank_points
        if not self._root_widget:
            return
        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_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 = 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))
                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_account_misc_read_val('proPowerRankingBoost', 0.0)) * 0.01
        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.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 = (get_league_rank_points(data, 'trophyCount'))
        total_trophies_value = (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(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
예제 #22
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.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.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_account_misc_read_val('tickets2Amount', 500)))])
        c3txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets3Amount',
                                                     1500)))])
        c4txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets4Amount',
                                                     5000)))])
        c5txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_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_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_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().split('${COUNT}')[0].strip())
        txt2 = (ba.Lstr(
            resource=self._r +
            '.youHaveText').evaluate().split('${COUNT}')[-1].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
예제 #23
0
    def _refresh(self) -> None:
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        from bastd.ui.confirm import QuitWindow
        from bastd.ui.store.button import StoreButton

        # Clear everything that was there.
        children = self._root_widget.get_children()
        for child in children:
            child.delete()

        self._tdelay = 0.0
        self._t_delay_inc = 0.0
        self._t_delay_play = 0.0
        self._button_width = 200.0
        self._button_height = 45.0

        self._r = 'mainMenu'

        app = ba.app
        self._have_quit_button = (app.ui.uiscale is ba.UIScale.LARGE
                                  or (app.platform == 'windows'
                                      and app.subplatform == 'oculus'))

        self._have_store_button = not self._in_game

        self._have_settings_button = (
            (not self._in_game or not app.toolbar_test)
            and not (self._is_demo or self._is_arcade or self._is_iircade))

        self._input_device = input_device = _ba.get_ui_input_device()
        self._input_player = input_device.player if input_device else None
        self._connected_to_remote_player = (
            input_device.is_connected_to_remote_player()
            if input_device else False)

        positions: List[Tuple[float, float, float]] = []
        self._p_index = 0

        if self._in_game:
            h, v, scale = self._refresh_in_game(positions)
        else:
            h, v, scale = self._refresh_not_in_game(positions)

        if self._have_settings_button:
            h, v, scale = positions[self._p_index]
            self._p_index += 1
            self._settings_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(h - self._button_width * 0.5 * scale, v),
                size=(self._button_width, self._button_height),
                scale=scale,
                autoselect=self._use_autoselect,
                label=ba.Lstr(resource=self._r + '.settingsText'),
                transition_delay=self._tdelay,
                on_activate_call=self._settings)

        # Scattered eggs on easter.
        if _ba.get_account_misc_read_val('easter',
                                         False) and not self._in_game:
            icon_size = 34
            ba.imagewidget(parent=self._root_widget,
                           position=(h - icon_size * 0.5 - 15,
                                     v + self._button_height * scale -
                                     icon_size * 0.24 + 1.5),
                           transition_delay=self._tdelay,
                           size=(icon_size, icon_size),
                           texture=ba.gettexture('egg3'),
                           tilt_scale=0.0)

        self._tdelay += self._t_delay_inc

        if self._in_game:
            h, v, scale = positions[self._p_index]
            self._p_index += 1

            # If we're in a replay, we have a 'Leave Replay' button.
            if _ba.is_in_replay():
                ba.buttonwidget(parent=self._root_widget,
                                position=(h - self._button_width * 0.5 * scale,
                                          v),
                                scale=scale,
                                size=(self._button_width, self._button_height),
                                autoselect=self._use_autoselect,
                                label=ba.Lstr(resource='replayEndText'),
                                on_activate_call=self._confirm_end_replay)
            elif _ba.get_foreground_host_session() is not None:
                ba.buttonwidget(
                    parent=self._root_widget,
                    position=(h - self._button_width * 0.5 * scale, v),
                    scale=scale,
                    size=(self._button_width, self._button_height),
                    autoselect=self._use_autoselect,
                    label=ba.Lstr(resource=self._r + '.endGameText'),
                    on_activate_call=self._confirm_end_game)
            # Assume we're in a client-session.
            else:
                ba.buttonwidget(
                    parent=self._root_widget,
                    position=(h - self._button_width * 0.5 * scale, v),
                    scale=scale,
                    size=(self._button_width, self._button_height),
                    autoselect=self._use_autoselect,
                    label=ba.Lstr(resource=self._r + '.leavePartyText'),
                    on_activate_call=self._confirm_leave_party)

        self._store_button: Optional[ba.Widget]
        if self._have_store_button:
            this_b_width = self._button_width
            h, v, scale = positions[self._p_index]
            self._p_index += 1

            sbtn = self._store_button_instance = StoreButton(
                parent=self._root_widget,
                position=(h - this_b_width * 0.5 * scale, v),
                size=(this_b_width, self._button_height),
                scale=scale,
                on_activate_call=ba.WeakCall(self._on_store_pressed),
                sale_scale=1.3,
                transition_delay=self._tdelay)
            self._store_button = store_button = sbtn.get_button()
            uiscale = ba.app.ui.uiscale
            icon_size = (55 if uiscale is ba.UIScale.SMALL else
                         55 if uiscale is ba.UIScale.MEDIUM else 70)
            ba.imagewidget(
                parent=self._root_widget,
                position=(h - icon_size * 0.5,
                          v + self._button_height * scale - icon_size * 0.23),
                transition_delay=self._tdelay,
                size=(icon_size, icon_size),
                texture=ba.gettexture(self._store_char_tex),
                tilt_scale=0.0,
                draw_controller=store_button)

            self._tdelay += self._t_delay_inc
        else:
            self._store_button = None

        self._quit_button: Optional[ba.Widget]
        if not self._in_game and self._have_quit_button:
            h, v, scale = positions[self._p_index]
            self._p_index += 1
            self._quit_button = quit_button = ba.buttonwidget(
                parent=self._root_widget,
                autoselect=self._use_autoselect,
                position=(h - self._button_width * 0.5 * scale, v),
                size=(self._button_width, self._button_height),
                scale=scale,
                label=ba.Lstr(resource=self._r +
                              ('.quitText' if 'Mac' in
                               ba.app.user_agent_string else '.exitGameText')),
                on_activate_call=self._quit,
                transition_delay=self._tdelay)

            # Scattered eggs on easter.
            if _ba.get_account_misc_read_val('easter', False):
                icon_size = 30
                ba.imagewidget(parent=self._root_widget,
                               position=(h - icon_size * 0.5 + 25,
                                         v + self._button_height * scale -
                                         icon_size * 0.24 + 1.5),
                               transition_delay=self._tdelay,
                               size=(icon_size, icon_size),
                               texture=ba.gettexture('egg1'),
                               tilt_scale=0.0)

            ba.containerwidget(edit=self._root_widget,
                               cancel_button=quit_button)
            self._tdelay += self._t_delay_inc
        else:
            self._quit_button = None

            # If we're not in-game, have no quit button, and this is android,
            # we want back presses to quit our activity.
            if (not self._in_game and not self._have_quit_button
                    and ba.app.platform == 'android'):

                def _do_quit() -> None:
                    QuitWindow(swish=True, back=True)

                ba.containerwidget(edit=self._root_widget,
                                   on_cancel_call=_do_quit)

        # Add speed-up/slow-down buttons for replays.
        # (ideally this should be part of a fading-out playback bar like most
        # media players but this works for now).
        if _ba.is_in_replay():
            b_size = 50.0
            b_buffer = 10.0
            t_scale = 0.75
            uiscale = ba.app.ui.uiscale
            if uiscale is ba.UIScale.SMALL:
                b_size *= 0.6
                b_buffer *= 1.0
                v_offs = -40
                t_scale = 0.5
            elif uiscale is ba.UIScale.MEDIUM:
                v_offs = -70
            else:
                v_offs = -100
            self._replay_speed_text = ba.textwidget(
                parent=self._root_widget,
                text=ba.Lstr(resource='watchWindow.playbackSpeedText',
                             subs=[('${SPEED}', str(1.23))]),
                position=(h, v + v_offs + 7 * t_scale),
                h_align='center',
                v_align='center',
                size=(0, 0),
                scale=t_scale)

            # Update to current value.
            self._change_replay_speed(0)

            # Keep updating in a timer in case it gets changed elsewhere.
            self._change_replay_speed_timer = ba.Timer(
                0.25,
                ba.WeakCall(self._change_replay_speed, 0),
                timetype=ba.TimeType.REAL,
                repeat=True)
            btn = ba.buttonwidget(parent=self._root_widget,
                                  position=(h - b_size - b_buffer,
                                            v - b_size - b_buffer + v_offs),
                                  button_type='square',
                                  size=(b_size, b_size),
                                  label='',
                                  autoselect=True,
                                  on_activate_call=ba.Call(
                                      self._change_replay_speed, -1))
            ba.textwidget(
                parent=self._root_widget,
                draw_controller=btn,
                text='-',
                position=(h - b_size * 0.5 - b_buffer,
                          v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs),
                h_align='center',
                v_align='center',
                size=(0, 0),
                scale=3.0 * t_scale)
            btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(h + b_buffer, v - b_size - b_buffer + v_offs),
                button_type='square',
                size=(b_size, b_size),
                label='',
                autoselect=True,
                on_activate_call=ba.Call(self._change_replay_speed, 1))
            ba.textwidget(
                parent=self._root_widget,
                draw_controller=btn,
                text='+',
                position=(h + b_size * 0.5 + b_buffer,
                          v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs),
                h_align='center',
                v_align='center',
                size=(0, 0),
                scale=3.0 * t_scale)
예제 #24
0
 def power_ranking_value(self) -> int:
     """Get the power-ranking award value for this achievement."""
     val: int = _ba.get_account_misc_read_val(
         'achLeaguePoints.' + self._name, self._award)
     assert isinstance(val, int)
     return val
예제 #25
0
    def __init__(self,
                 account_id: str,
                 profile_id: str = None,
                 position: Tuple[float, float] = (0.0, 0.0),
                 scale: float = None,
                 offset: Tuple[float, float] = (0.0, 0.0)):
        from ba.internal import is_browser_likely_available, master_server_get

        self._account_id = account_id
        self._profile_id = profile_id

        uiscale = ba.app.uiscale
        if scale is None:
            scale = (2.6 if uiscale is ba.UIScale.SMALL else
                     1.8 if uiscale is ba.UIScale.MEDIUM else 1.4)
        self._transitioning_out = False

        self._width = 400
        self._height = (300 if uiscale is ba.UIScale.SMALL else
                        400 if uiscale is ba.UIScale.MEDIUM else 450)
        self._subcontainer: Optional[ba.Widget] = None

        bg_color = (0.5, 0.4, 0.6)

        # Creates our _root_widget.
        popup.PopupWindow.__init__(self,
                                   position=position,
                                   size=(self._width, self._height),
                                   scale=scale,
                                   bg_color=bg_color,
                                   offset=offset)

        self._cancel_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(50, self._height - 30),
            size=(50, 50),
            scale=0.5,
            label='',
            color=bg_color,
            on_activate_call=self._on_cancel_press,
            autoselect=True,
            icon=ba.gettexture('crossOut'),
            iconscale=1.2)

        self._title_text = ba.textwidget(
            parent=self.root_widget,
            position=(self._width * 0.5, self._height - 20),
            size=(0, 0),
            h_align='center',
            v_align='center',
            scale=0.6,
            text=ba.Lstr(resource='playerInfoText'),
            maxwidth=200,
            color=(0.7, 0.7, 0.7, 0.7))

        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
                                             size=(self._width - 60,
                                                   self._height - 70),
                                             position=(30, 30),
                                             capture_arrows=True,
                                             simple_culling_v=10)
        ba.widget(edit=self._scrollwidget, autoselect=True)

        self._loading_text = ba.textwidget(
            parent=self._scrollwidget,
            scale=0.5,
            text=ba.Lstr(value='${A}...',
                         subs=[('${A}', ba.Lstr(resource='loadingText'))]),
            size=(self._width - 60, 100),
            h_align='center',
            v_align='center')

        # In cases where the user most likely has a browser/email, lets
        # offer a 'report this user' button.
        if (is_browser_likely_available() and _ba.get_account_misc_read_val(
                'showAccountExtrasMenu', False)):

            self._extras_menu_button = ba.buttonwidget(
                parent=self.root_widget,
                size=(20, 20),
                position=(self._width - 60, self._height - 30),
                autoselect=True,
                label='...',
                button_type='square',
                color=(0.64, 0.52, 0.69),
                textcolor=(0.57, 0.47, 0.57),
                on_activate_call=self._on_extras_menu_press)

        ba.containerwidget(edit=self.root_widget,
                           cancel_button=self._cancel_button)

        master_server_get('bsAccountInfo', {
            'buildNumber': ba.app.build_number,
            'accountID': self._account_id,
            'profileID': self._profile_id
        },
                          callback=ba.WeakCall(self._on_query_response))
예제 #26
0
def get_store_layout() -> Dict[str, List[Dict[str, Any]]]:
    """Return what's available in the store at a given time.

        Categorized by tab and by section."""
    if _ba.app.store_layout is None:
        _ba.app.store_layout = {
            'characters': [{
                'items': []
            }],
            'extras': [{
                'items': ['pro']
            }],
            'maps': [{
                'items': ['maps.lake_frigid']
            }],
            'minigames': [],
            'icons': [{
                'items': [
                    'icons.mushroom',
                    'icons.heart',
                    'icons.eyeball',
                    'icons.yinyang',
                    'icons.hal',
                    'icons.flag_us',
                    'icons.flag_mexico',
                    'icons.flag_germany',
                    'icons.flag_brazil',
                    'icons.flag_russia',
                    'icons.flag_china',
                    'icons.flag_uk',
                    'icons.flag_canada',
                    'icons.flag_india',
                    'icons.flag_japan',
                    'icons.flag_france',
                    'icons.flag_indonesia',
                    'icons.flag_italy',
                    'icons.flag_south_korea',
                    'icons.flag_netherlands',
                    'icons.flag_uae',
                    'icons.flag_qatar',
                    'icons.flag_egypt',
                    'icons.flag_kuwait',
                    'icons.flag_algeria',
                    'icons.flag_saudi_arabia',
                    'icons.flag_malaysia',
                    'icons.flag_czech_republic',
                    'icons.flag_australia',
                    'icons.flag_singapore',
                    'icons.flag_iran',
                    'icons.flag_poland',
                    'icons.flag_argentina',
                    'icons.flag_philippines',
                    'icons.flag_chile',
                    'icons.moon',
                    'icons.fedora',
                    'icons.spider',
                    'icons.ninja_star',
                    'icons.skull',
                    'icons.dragon',
                    'icons.viking_helmet',
                    'icons.fireball',
                    'icons.helmet',
                    'icons.crown',
                ]
            }]
        }
    store_layout = _ba.app.store_layout
    assert store_layout is not None
    store_layout['characters'] = [{
        'items': [
            'characters.kronk', 'characters.zoe', 'characters.jackmorgan',
            'characters.mel', 'characters.snakeshadow', 'characters.bones',
            'characters.bernard', 'characters.agent', 'characters.frosty',
            'characters.pascal', 'characters.pixie'
        ]
    }]
    store_layout['minigames'] = [{
        'items':
        ['games.ninja_fight', 'games.meteor_shower', 'games.target_practice']
    }]
    if _ba.get_account_misc_read_val('xmas', False):
        store_layout['characters'][0]['items'].append('characters.santa')
    store_layout['characters'][0]['items'].append('characters.wizard')
    store_layout['characters'][0]['items'].append('characters.cyborg')
    if _ba.get_account_misc_read_val('easter', False):
        store_layout['characters'].append({
            'title': 'store.holidaySpecialText',
            'items': ['characters.bunny']
        })
        store_layout['minigames'].append({
            'title': 'store.holidaySpecialText',
            'items': ['games.easter_egg_hunt']
        })
    return store_layout
예제 #27
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.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_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.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)
예제 #28
0
def get_available_sale_time(tab: str) -> Optional[int]:
    """(internal)"""
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-nested-blocks
    # pylint: disable=too-many-locals
    try:
        import datetime
        from ba._generated.enums import TimeType, TimeFormat
        app = _ba.app
        sale_times: List[Optional[int]] = []

        # Calc time for our pro sale (old special case).
        if tab == 'extras':
            config = app.config
            if app.accounts.have_pro():
                return None

            # If we haven't calced/loaded start times yet.
            if app.pro_sale_start_time is None:

                # If we've got a time-remaining in our config, start there.
                if 'PSTR' in config:
                    app.pro_sale_start_time = int(
                        _ba.time(TimeType.REAL, TimeFormat.MILLISECONDS))
                    app.pro_sale_start_val = config['PSTR']
                else:

                    # We start the timer once we get the duration from
                    # the server.
                    start_duration = _ba.get_account_misc_read_val(
                        'proSaleDurationMinutes', None)
                    if start_duration is not None:
                        app.pro_sale_start_time = int(
                            _ba.time(TimeType.REAL, TimeFormat.MILLISECONDS))
                        app.pro_sale_start_val = (60000 * start_duration)

                    # If we haven't heard from the server yet, no sale..
                    else:
                        return None

            assert app.pro_sale_start_val is not None
            val: Optional[int] = max(
                0, app.pro_sale_start_val -
                (_ba.time(TimeType.REAL, TimeFormat.MILLISECONDS) -
                 app.pro_sale_start_time))

            # Keep the value in the config up to date. I suppose we should
            # write the config occasionally but it should happen often enough
            # for other reasons.
            config['PSTR'] = val
            if val == 0:
                val = None
            sale_times.append(val)

        # Now look for sales in this tab.
        sales_raw = _ba.get_account_misc_read_val('sales', {})
        store_layout = get_store_layout()
        for section in store_layout[tab]:
            for item in section['items']:
                if item in sales_raw:
                    if not _ba.get_purchased(item):
                        to_end = ((datetime.datetime.utcfromtimestamp(
                            sales_raw[item]['e']) -
                                   datetime.datetime.utcnow()).total_seconds())
                        if to_end > 0:
                            sale_times.append(int(to_end * 1000))

        # Return the smallest time I guess?
        sale_times_int = [t for t in sale_times if isinstance(t, int)]
        return min(sale_times_int) if sale_times_int else None

    except Exception:
        from ba import _error
        _error.print_exception('error calcing sale time')
        return None
예제 #29
0
    def update_buttons(self) -> None:
        """Update our buttons."""
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import have_pro, get_available_sale_time
        from ba import SpecialChar
        if not self._root_widget:
            return
        import datetime
        sales_raw = _ba.get_account_misc_read_val('sales', {})
        sales = {}
        try:
            # Look at the current set of sales; filter any with time remaining.
            for sale_item, sale_info in list(sales_raw.items()):
                to_end = (datetime.datetime.utcfromtimestamp(sale_info['e']) -
                          datetime.datetime.utcnow()).total_seconds()
                if to_end > 0:
                    sales[sale_item] = {
                        'to_end': to_end,
                        'original_price': sale_info['op']
                    }
        except Exception:
            ba.print_exception('Error parsing sales.')

        assert self.button_infos is not None
        for b_type, b_info in self.button_infos.items():

            if b_type in ['upgrades.pro', 'pro']:
                purchased = have_pro()
            else:
                purchased = _ba.get_purchased(b_type)

            sale_opacity = 0.0
            sale_title_text: Union[str, ba.Lstr] = ''
            sale_time_text: Union[str, ba.Lstr] = ''

            if purchased:
                title_color = (0.8, 0.7, 0.9, 1.0)
                color = (0.63, 0.55, 0.78)
                extra_image_opacity = 0.5
                call = ba.WeakCall(self._print_already_own, b_info['name'])
                price_text = ''
                price_text_left = ''
                price_text_right = ''
                show_purchase_check = True
                description_color: Sequence[float] = (0.4, 1.0, 0.4, 0.4)
                description_color2: Sequence[float] = (0.0, 0.0, 0.0, 0.0)
                price_color = (0.5, 1, 0.5, 0.3)
            else:
                title_color = (0.7, 0.9, 0.7, 1.0)
                color = (0.4, 0.8, 0.1)
                extra_image_opacity = 1.0
                call = b_info['call'] if 'call' in b_info else None
                if b_type in ['upgrades.pro', 'pro']:
                    sale_time = get_available_sale_time('extras')
                    if sale_time is not None:
                        priceraw = _ba.get_price('pro')
                        price_text_left = (priceraw
                                           if priceraw is not None else '?')
                        priceraw = _ba.get_price('pro_sale')
                        price_text_right = (priceraw
                                            if priceraw is not None else '?')
                        sale_opacity = 1.0
                        price_text = ''
                        sale_title_text = ba.Lstr(resource='store.saleText')
                        sale_time_text = ba.timestring(
                            sale_time,
                            centi=False,
                            timeformat=ba.TimeFormat.MILLISECONDS)
                    else:
                        priceraw = _ba.get_price('pro')
                        price_text = priceraw if priceraw is not None else '?'
                        price_text_left = ''
                        price_text_right = ''
                else:
                    price = _ba.get_account_misc_read_val('price.' + b_type, 0)

                    # Color the button differently if we cant afford this.
                    if _ba.get_account_state() == 'signed_in':
                        if _ba.get_account_ticket_count() < price:
                            color = (0.6, 0.61, 0.6)
                    price_text = ba.charstr(ba.SpecialChar.TICKET) + str(
                        _ba.get_account_misc_read_val('price.' + b_type, '?'))
                    price_text_left = ''
                    price_text_right = ''

                    # TESTING:
                    if b_type in sales:
                        sale_opacity = 1.0
                        price_text_left = ba.charstr(SpecialChar.TICKET) + str(
                            sales[b_type]['original_price'])
                        price_text_right = price_text
                        price_text = ''
                        sale_title_text = ba.Lstr(resource='store.saleText')
                        sale_time_text = ba.timestring(
                            int(sales[b_type]['to_end'] * 1000),
                            centi=False,
                            timeformat=ba.TimeFormat.MILLISECONDS)

                description_color = (0.5, 1.0, 0.5)
                description_color2 = (0.3, 1.0, 1.0)
                price_color = (0.2, 1, 0.2, 1.0)
                show_purchase_check = False

            if 'title_text' in b_info:
                ba.textwidget(edit=b_info['title_text'], color=title_color)
            if 'purchase_check' in b_info:
                ba.imagewidget(edit=b_info['purchase_check'],
                               opacity=1.0 if show_purchase_check else 0.0)
            if 'price_widget' in b_info:
                ba.textwidget(edit=b_info['price_widget'],
                              text=price_text,
                              color=price_color)
            if 'price_widget_left' in b_info:
                ba.textwidget(edit=b_info['price_widget_left'],
                              text=price_text_left)
            if 'price_widget_right' in b_info:
                ba.textwidget(edit=b_info['price_widget_right'],
                              text=price_text_right)
            if 'price_slash_widget' in b_info:
                ba.imagewidget(edit=b_info['price_slash_widget'],
                               opacity=sale_opacity)
            if 'sale_bg_widget' in b_info:
                ba.imagewidget(edit=b_info['sale_bg_widget'],
                               opacity=sale_opacity)
            if 'sale_title_widget' in b_info:
                ba.textwidget(edit=b_info['sale_title_widget'],
                              text=sale_title_text)
            if 'sale_time_widget' in b_info:
                ba.textwidget(edit=b_info['sale_time_widget'],
                              text=sale_time_text)
            if 'button' in b_info:
                ba.buttonwidget(edit=b_info['button'],
                                color=color,
                                on_activate_call=call)
            if 'extra_backings' in b_info:
                for bck in b_info['extra_backings']:
                    ba.imagewidget(edit=bck,
                                   color=color,
                                   opacity=extra_image_opacity)
            if 'extra_images' in b_info:
                for img in b_info['extra_images']:
                    ba.imagewidget(edit=img, opacity=extra_image_opacity)
            if 'extra_texts' in b_info:
                for etxt in b_info['extra_texts']:
                    ba.textwidget(edit=etxt, color=description_color)
            if 'extra_texts_2' in b_info:
                for etxt in b_info['extra_texts_2']:
                    ba.textwidget(edit=etxt, color=description_color2)
            if 'descriptionText' in b_info:
                ba.textwidget(edit=b_info['descriptionText'],
                              color=description_color)
예제 #30
0
    def __init__(self,
                 edit_profile_window: EditProfileWindow,
                 transition: str = 'in_right'):
        from ba.internal import master_server_get
        self._r = 'editProfileWindow'

        self._width = 680
        self._height = 350
        uiscale = ba.app.uiscale
        self._base_scale = (2.05 if uiscale is ba.UIScale.SMALL else
                            1.5 if uiscale is ba.UIScale.MEDIUM else 1.2)
        self._upgrade_start_time: Optional[float] = None
        self._name = edit_profile_window.getname()
        self._edit_profile_window = weakref.ref(edit_profile_window)

        top_extra = 15 if uiscale is ba.UIScale.SMALL else 15
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            toolbar_visibility='menu_currency',
            transition=transition,
            scale=self._base_scale,
            stack_offset=(0, 15) if uiscale is ba.UIScale.SMALL else (0, 0)))
        cancel_button = ba.buttonwidget(parent=self._root_widget,
                                        position=(52, 30),
                                        size=(155, 60),
                                        scale=0.8,
                                        autoselect=True,
                                        label=ba.Lstr(resource='cancelText'),
                                        on_activate_call=self._cancel)
        self._upgrade_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(self._width - 190, 30),
            size=(155, 60),
            scale=0.8,
            autoselect=True,
            label=ba.Lstr(resource='upgradeText'),
            on_activate_call=self._on_upgrade_press)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=cancel_button,
                           start_button=self._upgrade_button,
                           selected_child=self._upgrade_button)

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 38),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.upgradeToGlobalProfileText'),
                      color=ba.app.title_color,
                      maxwidth=self._width * 0.45,
                      scale=1.0,
                      h_align='center',
                      v_align='center')

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 100),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.upgradeProfileInfoText'),
                      color=ba.app.infotextcolor,
                      maxwidth=self._width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')

        self._status_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height - 160),
            size=(0, 0),
            text=ba.Lstr(resource=self._r + '.checkingAvailabilityText',
                         subs=[('${NAME}', self._name)]),
            color=(0.8, 0.4, 0.0),
            maxwidth=self._width * 0.8,
            scale=0.65,
            h_align='center',
            v_align='center')

        self._price_text = ba.textwidget(parent=self._root_widget,
                                         position=(self._width * 0.5,
                                                   self._height - 230),
                                         size=(0, 0),
                                         text='',
                                         color=(0.2, 1, 0.2),
                                         maxwidth=self._width * 0.8,
                                         scale=1.5,
                                         h_align='center',
                                         v_align='center')

        self._tickets_text: Optional[ba.Widget]
        if not ba.app.toolbars:
            self._tickets_text = ba.textwidget(
                parent=self._root_widget,
                position=(self._width * 0.9 - 5, self._height - 30),
                size=(0, 0),
                text=ba.charstr(ba.SpecialChar.TICKET) + '123',
                color=(0.2, 1, 0.2),
                maxwidth=100,
                scale=0.5,
                h_align='right',
                v_align='center')
        else:
            self._tickets_text = None

        master_server_get('bsGlobalProfileCheck', {
            'name': self._name,
            'b': ba.app.build_number
        },
                          callback=ba.WeakCall(self._profile_check_result))
        self._cost = _ba.get_account_misc_read_val('price.global_profile', 500)
        self._status: Optional[str] = 'waiting'
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()