Example #1
0
    def _handle_hit(self, msg: ba.HitMessage) -> None:
        ispunched = (msg.srcnode and msg.srcnode.getnodetype() == 'spaz')

        # Normal bombs are triggered by non-punch impacts;
        # impact-bombs by all impacts.
        if (not self._exploded and
            (not ispunched or self.bomb_type in ['impact', 'land_mine'])):

            # Also lets change the owner of the bomb to whoever is setting
            # us off. (this way points for big chain reactions go to the
            # person causing them).
            source_player = msg.get_source_player(ba.Player)
            if source_player is not None:
                self._source_player = source_player

                # Also inherit the hit type (if a landmine sets off by a bomb,
                # the credit should go to the mine)
                # the exception is TNT.  TNT always gets credit.
                # UPDATE (July 2020): not doing this anymore. Causes too much
                # weird logic such as bombs acting like punches. Holler if
                # anything is noticeably broken due to this.
                # if self.bomb_type != 'tnt':
                #     self.hit_type = msg.hit_type
                #     self.hit_subtype = msg.hit_subtype

            ba.timer(0.1 + random.random() * 0.1,
                     ba.WeakCall(self.handlemessage, ExplodeMessage()))
        assert self.node
        self.node.handlemessage('impulse', msg.pos[0], msg.pos[1], msg.pos[2],
                                msg.velocity[0], msg.velocity[1],
                                msg.velocity[2], msg.magnitude,
                                msg.velocity_magnitude, msg.radius, 0,
                                msg.velocity[0], msg.velocity[1],
                                msg.velocity[2])

        if msg.srcnode:
            pass
Example #2
0
    def _drop_powerups(self,
                       standard_points: bool = False,
                       force_first: str = None) -> None:
        """Generic powerup drop."""
        from bastd.actor import powerupbox
        if standard_points:
            pts = self.map.powerup_spawn_points
            for i in range(len(pts)):
                ba.timer(
                    1.0 + i * 0.5,
                    ba.WeakCall(self._drop_powerup, i,
                                force_first if i == 0 else None))
        else:
            drop_pt = (self._powerup_center[0] + random.uniform(
                -1.0 * self._powerup_spread[0], 1.0 * self._powerup_spread[0]),
                       self._powerup_center[1],
                       self._powerup_center[2] + random.uniform(
                           -self._powerup_spread[1], self._powerup_spread[1]))

            # Drop one random one somewhere.
            powerupbox.PowerupBox(
                position=drop_pt,
                poweruptype=powerupbox.get_factory().get_random_powerup_type(
                    excludetypes=self._excludepowerups)).autoretain()
Example #3
0
    def _refresh_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
        custom_menu_entries: List[Dict[str, Any]] = []
        session = _ba.get_foreground_host_session()
        if session is not None:
            try:
                custom_menu_entries = session.get_custom_menu_entries()
                for cme in custom_menu_entries:
                    if (not isinstance(cme, dict) or 'label' not in cme
                            or not isinstance(cme['label'], (str, ba.Lstr))
                            or 'call' not in cme or not callable(cme['call'])):
                        raise ValueError('invalid custom menu entry: ' +
                                         str(cme))
            except Exception:
                custom_menu_entries = []
                ba.print_exception(
                    f'Error getting custom menu entries for {session}')
        self._width = 250.0
        self._height = 250.0 if self._input_player else 180.0
        if (self._is_demo or self._is_arcade) and self._input_player:
            self._height -= 40
        if not self._have_settings_button:
            self._height -= 50
        if self._connected_to_remote_player:
            # In this case we have a leave *and* a disconnect button.
            self._height += 50
        self._height += 50 * (len(custom_menu_entries))
        uiscale = ba.app.ui.uiscale
        ba.containerwidget(
            edit=self._root_widget,
            size=(self._width, self._height),
            scale=(2.15 if uiscale is ba.UIScale.SMALL else
                   1.6 if uiscale is ba.UIScale.MEDIUM else 1.0))
        h = 125.0
        v = (self._height - 80.0 if self._input_player else self._height - 60)
        h_offset = 0
        d_h_offset = 0
        v_offset = -50
        for _i in range(6 + len(custom_menu_entries)):
            positions.append((h, v, 1.0))
            v += v_offset
            h += h_offset
            h_offset += d_h_offset
        self._start_button = None
        ba.app.pause()

        # Player name if applicable.
        if self._input_player:
            player_name = self._input_player.getname()
            h, v, scale = positions[self._p_index]
            v += 35
            ba.textwidget(parent=self._root_widget,
                          position=(h - self._button_width / 2, v),
                          size=(self._button_width, self._button_height),
                          color=(1, 1, 1, 0.5),
                          scale=0.7,
                          h_align='center',
                          text=ba.Lstr(value=player_name))
        else:
            player_name = ''
        h, v, scale = positions[self._p_index]
        self._p_index += 1
        btn = ba.buttonwidget(parent=self._root_widget,
                              position=(h - self._button_width / 2, v),
                              size=(self._button_width, self._button_height),
                              scale=scale,
                              label=ba.Lstr(resource=self._r + '.resumeText'),
                              autoselect=self._use_autoselect,
                              on_activate_call=self._resume)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        # Add any custom options defined by the current game.
        for entry in custom_menu_entries:
            h, v, scale = positions[self._p_index]
            self._p_index += 1

            # Ask the entry whether we should resume when we call
            # it (defaults to true).
            resume = bool(entry.get('resume_on_call', True))

            if resume:
                call = ba.Call(self._resume_and_call, entry['call'])
            else:
                call = ba.Call(entry['call'], ba.WeakCall(self._resume))

            ba.buttonwidget(parent=self._root_widget,
                            position=(h - self._button_width / 2, v),
                            size=(self._button_width, self._button_height),
                            scale=scale,
                            on_activate_call=call,
                            label=entry['label'],
                            autoselect=self._use_autoselect)
        # Add a 'leave' button if the menu-owner has a player.
        if ((self._input_player or self._connected_to_remote_player)
                and not (self._is_demo or self._is_arcade)):
            h, v, scale = positions[self._p_index]
            self._p_index += 1
            btn = ba.buttonwidget(parent=self._root_widget,
                                  position=(h - self._button_width / 2, v),
                                  size=(self._button_width,
                                        self._button_height),
                                  scale=scale,
                                  on_activate_call=self._leave,
                                  label='',
                                  autoselect=self._use_autoselect)

            if (player_name != '' and player_name[0] != '<'
                    and player_name[-1] != '>'):
                txt = ba.Lstr(resource=self._r + '.justPlayerText',
                              subs=[('${NAME}', player_name)])
            else:
                txt = ba.Lstr(value=player_name)
            ba.textwidget(parent=self._root_widget,
                          position=(h, v + self._button_height *
                                    (0.64 if player_name != '' else 0.5)),
                          size=(0, 0),
                          text=ba.Lstr(resource=self._r + '.leaveGameText'),
                          scale=(0.83 if player_name != '' else 1.0),
                          color=(0.75, 1.0, 0.7),
                          h_align='center',
                          v_align='center',
                          draw_controller=btn,
                          maxwidth=self._button_width * 0.9)
            ba.textwidget(parent=self._root_widget,
                          position=(h, v + self._button_height * 0.27),
                          size=(0, 0),
                          text=txt,
                          color=(0.75, 1.0, 0.7),
                          h_align='center',
                          v_align='center',
                          draw_controller=btn,
                          scale=0.45,
                          maxwidth=self._button_width * 0.9)
        return h, v, scale
Example #4
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements

        # 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 = 'editSoundtrackWindow'
        uiscale = ba.app.uiscale
        self._width = 800 if uiscale is ba.UIScale.SMALL else 600
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (340 if uiscale is ba.UIScale.SMALL else
                        370 if uiscale is ba.UIScale.MEDIUM else 440)
        spacing = 40.0
        v = self._height - 40.0
        v -= spacing * 1.0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(2.3 if uiscale is ba.UIScale.SMALL else
                   1.6 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -18) if uiscale is ba.UIScale.SMALL else (0, 0)))

        if ba.app.toolbars and uiscale is ba.UIScale.SMALL:
            self._back_button = None
        else:
            self._back_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(45 + x_inset, self._height - 60),
                size=(120, 60),
                scale=0.8,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                autoselect=True)
            ba.buttonwidget(edit=self._back_button,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))
        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 35),
                      size=(0, 0),
                      maxwidth=300,
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.title_color,
                      h_align='center',
                      v_align='center')

        h = 43 + x_inset
        v = self._height - 60
        b_color = (0.6, 0.53, 0.63)
        b_textcolor = (0.75, 0.7, 0.8)
        lock_tex = ba.gettexture('lock')
        self._lock_images: List[ba.Widget] = []

        scl = (1.0 if uiscale is ba.UIScale.SMALL else
               1.13 if uiscale is ba.UIScale.MEDIUM else 1.4)
        v -= 60.0 * scl
        self._new_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._new_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.newText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))

        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._edit_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._edit_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.editText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._duplicate_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._duplicate_soundtrack,
            button_type='square',
            autoselect=True,
            color=b_color,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.duplicateText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._delete_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._delete_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.deleteText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))

        # Keep our lock images up to date/etc.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()

        v = self._height - 65
        scroll_height = self._height - 105
        v -= scroll_height
        self._scrollwidget = scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            position=(152 + x_inset, v),
            highlight=False,
            size=(self._width - (205 + 2 * x_inset), scroll_height))
        ba.widget(edit=self._scrollwidget,
                  left_widget=self._new_button,
                  right_widget=_ba.get_special_widget('party_button')
                  if ba.app.toolbars else self._scrollwidget)
        self._col = ba.columnwidget(parent=scrollwidget)

        self._soundtracks: Optional[Dict[str, Any]] = None
        self._selected_soundtrack: Optional[str] = None
        self._selected_soundtrack_index: Optional[int] = None
        self._soundtrack_widgets: List[ba.Widget] = []
        self._allow_changing_soundtracks = False
        self._refresh()
        if self._back_button is not None:
            ba.buttonwidget(edit=self._back_button,
                            on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget,
                               cancel_button=self._back_button)
        else:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
Example #5
0
 def _start_powerup_drops(self) -> None:
     self._powerup_drop_timer = ba.Timer(3.0,
                                         ba.WeakCall(self._drop_powerups),
                                         repeat=True)
Example #6
0
 def __init__(self, window: StoreBrowserWindow):
     self._window = weakref.ref(window)
     data = {'tab': tab}
     ba.timer(0.1,
              ba.WeakCall(self._on_response, data),
              timetype=ba.TimeType.REAL)
Example #7
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)
Example #8
0
 def _select_with_delay(self, map_name: str) -> None:
     _ba.lock_all_input()
     ba.timer(0.1, _ba.unlock_all_input, timetype=ba.TimeType.REAL)
     ba.timer(0.1,
              ba.WeakCall(self._select, map_name),
              timetype=ba.TimeType.REAL)
    def __init__(self,
                 tournament_id: str,
                 tournament_activity: ba.Activity = None,
                 position: Tuple[float, float] = (0.0, 0.0),
                 delegate: Any = None,
                 scale: float = None,
                 offset: Tuple[float, float] = (0.0, 0.0),
                 on_close_call: Callable[[], Any] = None):
        # Needs some tidying.
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements

        ba.set_analytics_screen('Tournament Entry Window')

        self._tournament_id = tournament_id
        self._tournament_info = (ba.app.tournament_info[self._tournament_id])

        # Set a few vars depending on the tourney fee.
        self._fee = self._tournament_info['fee']
        self._allow_ads = self._tournament_info['allowAds']
        if self._fee == 4:
            self._purchase_name = 'tournament_entry_4'
            self._purchase_price_name = 'price.tournament_entry_4'
        elif self._fee == 3:
            self._purchase_name = 'tournament_entry_3'
            self._purchase_price_name = 'price.tournament_entry_3'
        elif self._fee == 2:
            self._purchase_name = 'tournament_entry_2'
            self._purchase_price_name = 'price.tournament_entry_2'
        elif self._fee == 1:
            self._purchase_name = 'tournament_entry_1'
            self._purchase_price_name = 'price.tournament_entry_1'
        else:
            if self._fee != 0:
                raise ValueError('invalid fee: ' + str(self._fee))
            self._purchase_name = 'tournament_entry_0'
            self._purchase_price_name = 'price.tournament_entry_0'

        self._purchase_price: Optional[int] = None

        self._on_close_call = on_close_call
        if scale is None:
            uiscale = ba.app.uiscale
            scale = (2.3 if uiscale is ba.UIScale.SMALL else
                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
        self._delegate = delegate
        self._transitioning_out = False

        self._tournament_activity = tournament_activity

        self._width = 340
        self._height = 220

        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,
                                   toolbar_visibility='menu_currency')

        self._last_ad_press_time = -9999.0
        self._last_ticket_press_time = -9999.0
        self._entering = False
        self._launched = False

        # Show the ad button only if we support ads *and* it has a level 1 fee.
        self._do_ad_btn = (_ba.has_video_ads() and self._allow_ads)

        x_offs = 0 if self._do_ad_btn else 85

        self._cancel_button = ba.buttonwidget(parent=self.root_widget,
                                              position=(20, self._height - 30),
                                              size=(50, 50),
                                              scale=0.5,
                                              label='',
                                              color=bg_color,
                                              on_activate_call=self._on_cancel,
                                              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='tournamentEntryText'),
            maxwidth=200,
            color=(1, 1, 1, 0.4))

        btn = self._pay_with_tickets_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(30 + x_offs, 60),
            autoselect=True,
            button_type='square',
            size=(120, 120),
            label='',
            on_activate_call=self._on_pay_with_tickets_press)
        self._ticket_img_pos = (50 + x_offs, 94)
        self._ticket_img_pos_free = (50 + x_offs, 80)
        self._ticket_img = ba.imagewidget(parent=self.root_widget,
                                          draw_controller=btn,
                                          size=(80, 80),
                                          position=self._ticket_img_pos,
                                          texture=ba.gettexture('tickets'))
        self._ticket_cost_text_position = (87 + x_offs, 88)
        self._ticket_cost_text_position_free = (87 + x_offs, 120)
        self._ticket_cost_text = ba.textwidget(
            parent=self.root_widget,
            draw_controller=btn,
            position=self._ticket_cost_text_position,
            size=(0, 0),
            h_align='center',
            v_align='center',
            scale=0.6,
            text='',
            maxwidth=95,
            color=(0, 1, 0))
        self._free_plays_remaining_text = ba.textwidget(
            parent=self.root_widget,
            draw_controller=btn,
            position=(87 + x_offs, 78),
            size=(0, 0),
            h_align='center',
            v_align='center',
            scale=0.33,
            text='',
            maxwidth=95,
            color=(0, 0.8, 0))
        self._pay_with_ad_btn: Optional[ba.Widget]
        if self._do_ad_btn:
            btn = self._pay_with_ad_btn = ba.buttonwidget(
                parent=self.root_widget,
                position=(190, 60),
                autoselect=True,
                button_type='square',
                size=(120, 120),
                label='',
                on_activate_call=self._on_pay_with_ad_press)
            self._pay_with_ad_img = ba.imagewidget(parent=self.root_widget,
                                                   draw_controller=btn,
                                                   size=(80, 80),
                                                   position=(210, 94),
                                                   texture=ba.gettexture('tv'))

            self._ad_text_position = (251, 88)
            self._ad_text_position_remaining = (251, 92)
            have_ad_tries_remaining = (
                self._tournament_info['adTriesRemaining'] is not None)
            self._ad_text = ba.textwidget(
                parent=self.root_widget,
                draw_controller=btn,
                position=self._ad_text_position_remaining
                if have_ad_tries_remaining else self._ad_text_position,
                size=(0, 0),
                h_align='center',
                v_align='center',
                scale=0.6,
                text=ba.Lstr(resource='watchAVideoText',
                             fallback_resource='watchAnAdText'),
                maxwidth=95,
                color=(0, 1, 0))
            ad_plays_remaining_text = (
                '' if not have_ad_tries_remaining else '' +
                str(self._tournament_info['adTriesRemaining']))
            self._ad_plays_remaining_text = ba.textwidget(
                parent=self.root_widget,
                draw_controller=btn,
                position=(251, 78),
                size=(0, 0),
                h_align='center',
                v_align='center',
                scale=0.33,
                text=ad_plays_remaining_text,
                maxwidth=95,
                color=(0, 0.8, 0))

            ba.textwidget(parent=self.root_widget,
                          position=(self._width * 0.5, 120),
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          scale=0.6,
                          text=ba.Lstr(resource='orText',
                                       subs=[('${A}', ''), ('${B}', '')]),
                          maxwidth=35,
                          color=(1, 1, 1, 0.5))
        else:
            self._pay_with_ad_btn = None

        self._get_tickets_button: Optional[ba.Widget]
        if not ba.app.toolbars:
            self._get_tickets_button = ba.buttonwidget(
                parent=self.root_widget,
                position=(self._width - 190 + 110, 15),
                autoselect=True,
                scale=0.6,
                size=(120, 60),
                textcolor=(0.2, 1, 0.2),
                label=ba.charstr(ba.SpecialChar.TICKET),
                color=(0.6, 0.4, 0.7),
                on_activate_call=self._on_get_tickets_press)
        else:
            self._get_tickets_button = None

        self._seconds_remaining = None

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

        # Let's also ask the server for info about this tournament
        # (time remaining, etc) so we can show the user time remaining,
        # disallow entry if time has run out, etc.
        xoffs = 104 if ba.app.toolbars else 0
        self._time_remaining_text = ba.textwidget(parent=self.root_widget,
                                                  position=(70 + xoffs, 23),
                                                  size=(0, 0),
                                                  h_align='center',
                                                  v_align='center',
                                                  text='-',
                                                  scale=0.65,
                                                  maxwidth=100,
                                                  flatness=1.0,
                                                  color=(0.7, 0.7, 0.7))
        self._time_remaining_label_text = ba.textwidget(
            parent=self.root_widget,
            position=(70 + xoffs, 40),
            size=(0, 0),
            h_align='center',
            v_align='center',
            text=ba.Lstr(resource='coopSelectWindow.timeRemainingText'),
            scale=0.45,
            flatness=1.0,
            maxwidth=100,
            color=(0.7, 0.7, 0.7))

        self._last_query_time: Optional[float] = None

        # If there seems to be a relatively-recent valid cached info for this
        # tournament, use it. Otherwise we'll kick off a query ourselves.
        if (self._tournament_id in ba.app.tournament_info
                and ba.app.tournament_info[self._tournament_id]['valid'] and
            (ba.time(ba.TimeType.REAL, ba.TimeFormat.MILLISECONDS) -
             ba.app.tournament_info[self._tournament_id]['timeReceived'] <
             1000 * 60 * 5)):
            try:
                info = ba.app.tournament_info[self._tournament_id]
                self._seconds_remaining = max(
                    0, info['timeRemaining'] - int(
                        (ba.time(ba.TimeType.REAL, ba.TimeFormat.MILLISECONDS)
                         - info['timeReceived']) / 1000))
                self._have_valid_data = True
                self._last_query_time = ba.time(ba.TimeType.REAL)
            except Exception:
                ba.print_exception('error using valid tourney data')
                self._have_valid_data = False
        else:
            self._have_valid_data = False

        self._fg_state = ba.app.fg_state
        self._running_query = False
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
        self._update()
        self._restore_state()
Example #10
0
 def end_game(self) -> None:
     # Tell our bots to celebrate just to rub it in.
     self._bots.final_celebrate()
     ba.setmusic(None)
     ba.pushcall(ba.WeakCall(self.do_end, 'defeat'))
Example #11
0
    def __init__(self,
                 parent: ba.Widget,
                 position: Tuple[float, float],
                 initial_color: Sequence[float] = (1.0, 1.0, 1.0),
                 delegate: Any = None,
                 scale: float = None,
                 offset: Tuple[float, float] = (0.0, 0.0),
                 tag: Any = ''):
        # pylint: disable=too-many-locals
        del parent  # Unused var.
        from ba.internal import get_player_colors
        c_raw = get_player_colors()
        assert len(c_raw) == 16
        self.colors = [c_raw[0:4], c_raw[4:8], c_raw[8:12], c_raw[12:16]]

        uiscale = ba.app.uiscale
        if scale is None:
            scale = (2.3 if uiscale is ba.UIScale.SMALL else
                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
        self._delegate = delegate
        self._transitioning_out = False
        self._tag = tag
        self._color = list(initial_color)
        self._last_press_time = ba.time(ba.TimeType.REAL,
                                        ba.TimeFormat.MILLISECONDS)
        self._last_press_color_name: Optional[str] = None
        self._last_press_increasing: Optional[bool] = None
        self._change_speed = 1.0
        width = 180.0
        height = 240.0

        # Creates our _root_widget.
        PopupWindow.__init__(self,
                             position=position,
                             size=(width, height),
                             scale=scale,
                             focus_position=(10, 10),
                             focus_size=(width - 20, height - 20),
                             bg_color=(0.5, 0.5, 0.5),
                             offset=offset)
        self._swatch = ba.imagewidget(parent=self.root_widget,
                                      position=(width * 0.5 - 50, height - 70),
                                      size=(100, 70),
                                      texture=ba.gettexture('buttonSquare'),
                                      color=(1, 0, 0))
        x = 50
        y = height - 90
        self._label_r: ba.Widget
        self._label_g: ba.Widget
        self._label_b: ba.Widget
        for color_name, color_val in [('r', (1, 0.15, 0.15)),
                                      ('g', (0.15, 1, 0.15)),
                                      ('b', (0.15, 0.15, 1))]:
            txt = ba.textwidget(parent=self.root_widget,
                                position=(x - 10, y),
                                size=(0, 0),
                                h_align='center',
                                color=color_val,
                                v_align='center',
                                text='0.12')
            setattr(self, '_label_' + color_name, txt)
            for b_label, bhval, binc in [('-', 30, False), ('+', 75, True)]:
                ba.buttonwidget(parent=self.root_widget,
                                position=(x + bhval, y - 15),
                                scale=0.8,
                                repeat=True,
                                text_scale=1.3,
                                size=(40, 40),
                                label=b_label,
                                autoselect=True,
                                enable_sound=False,
                                on_activate_call=ba.WeakCall(
                                    self._color_change_press, color_name,
                                    binc))
            y -= 42

        btn = ba.buttonwidget(parent=self.root_widget,
                              position=(width * 0.5 - 40, 10),
                              size=(80, 30),
                              text_scale=0.6,
                              color=(0.6, 0.6, 0.6),
                              textcolor=(0.7, 0.7, 0.7),
                              label=ba.Lstr(resource='doneText'),
                              on_activate_call=ba.WeakCall(
                                  self._transition_out),
                              autoselect=True)
        ba.containerwidget(edit=self.root_widget, start_button=btn)

        # Unlike the swatch picker, we stay open and constantly push our
        # color to the delegate, so start doing that.
        self._update_for_color()
Example #12
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
Example #13
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)
Example #14
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 origin_widget: ba.Widget = None):
        from ba.internal import get_cached_league_rank_data
        from ba.deprecated import get_resource
        ba.set_analytics_screen('League Rank Window')

        self._league_rank_data: Optional[Dict[str, Any]] = None
        self._modal = modal

        # 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._width = 1320 if ba.app.small_ui else 1120
        x_inset = 100 if ba.app.small_ui else 0
        self._height = (657
                        if ba.app.small_ui else 710 if ba.app.med_ui else 800)
        self._r = 'coopSelectWindow'
        self._rdict = get_resource(self._r)
        top_extra = 20 if ba.app.small_ui else 0

        self._league_url_arg = ''

        self._is_current_season = False
        self._can_do_more_button = True

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            stack_offset=(0, -15) if ba.app.small_ui else (
                0, 10) if ba.app.med_ui else (0, 0),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(
                1.2 if ba.app.small_ui else 0.93 if ba.app.med_ui else 0.8)))

        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(75 + x_inset,
                      self._height - 87 - (4 if ba.app.small_ui else 0)),
            size=(120, 60),
            scale=1.2,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if self._modal else 'backText'),
            button_type=None if self._modal else 'back',
            on_activate_call=self._back)

        self._title_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height - 56),
            size=(0, 0),
            text=ba.Lstr(
                resource='league.leagueRankText',
                fallback_resource='coopSelectWindow.powerRankingText'),
            h_align="center",
            color=ba.app.title_color,
            scale=1.4,
            maxwidth=600,
            v_align="center")

        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        position=(75 + x_inset, self._height - 87 -
                                  (2 if ba.app.small_ui else 0)),
                        size=(60, 55),
                        label=ba.charstr(ba.SpecialChar.BACK))

        self._scroll_width = self._width - (130 + 2 * x_inset)
        self._scroll_height = self._height - 160
        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             highlight=False,
                                             position=(65 + x_inset, 70),
                                             size=(self._scroll_width,
                                                   self._scroll_height),
                                             center_small_content=True)
        ba.widget(edit=self._scrollwidget, autoselect=True)
        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._back_button,
                           selected_child=self._back_button)

        self._last_power_ranking_query_time: Optional[float] = None
        self._doing_power_ranking_query = False

        self._subcontainer: Optional[ba.Widget] = None
        self._subcontainerwidth = 800
        self._subcontainerheight = 483
        self._power_ranking_score_widgets: List[ba.Widget] = []

        self._season_popup_menu: Optional[popup_ui.PopupMenu] = None
        self._requested_season: Optional[str] = None
        self._season: Optional[str] = None

        # take note of our account state; we'll refresh later if this changes
        self._account_state = _ba.get_account_state()

        self._refresh()
        self._restore_state()

        # if we've got cached power-ranking data already, display it
        info = get_cached_league_rank_data()
        if info is not None:
            self._update_for_league_rank_data(info)

        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update(show=(info is None))
Example #15
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))
Example #16
0
    def __init__(self, origin: Sequence[float] = (0, 0)):
        _ba.set_party_window_open(True)
        self._r = 'partyWindow'
        self._popup_type: Optional[str] = None
        self._popup_party_member_client_id: Optional[int] = None
        self._popup_party_member_is_host: Optional[bool] = None
        self._width = 500
        uiscale = ba.app.ui.uiscale
        self._height = (365 if uiscale is ba.UIScale.SMALL else
                        480 if uiscale is ba.UIScale.MEDIUM else 600)
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition='in_scale',
            color=(0.40, 0.55, 0.20),
            parent=_ba.get_special_widget('overlay_stack'),
            on_outside_click_call=self.close_with_sound,
            scale_origin_stack_offset=origin,
            scale=(2.0 if uiscale is ba.UIScale.SMALL else
                   1.35 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (
                240, 0) if uiscale is ba.UIScale.MEDIUM else (330, 20)))

        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              scale=0.7,
                                              position=(30, self._height - 47),
                                              size=(50, 50),
                                              label='',
                                              on_activate_call=self.close,
                                              autoselect=True,
                                              color=(0.45, 0.63, 0.15),
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)

        self._menu_button = ba.buttonwidget(
            parent=self._root_widget,
            scale=0.7,
            position=(self._width - 60, self._height - 47),
            size=(50, 50),
            label='...',
            autoselect=True,
            button_type='square',
            on_activate_call=ba.WeakCall(self._on_menu_button_press),
            color=(0.55, 0.73, 0.25),
            iconscale=1.2)

        info = _ba.get_connection_to_host_info()
        if info.get('name', '') != '':
            title = ba.Lstr(value=info['name'])
        else:
            title = ba.Lstr(resource=self._r + '.titleText')

        self._title_text = ba.textwidget(parent=self._root_widget,
                                         scale=0.9,
                                         color=(0.5, 0.7, 0.5),
                                         text=title,
                                         size=(0, 0),
                                         position=(self._width * 0.5,
                                                   self._height - 29),
                                         maxwidth=self._width * 0.7,
                                         h_align='center',
                                         v_align='center')

        self._empty_str = ba.textwidget(parent=self._root_widget,
                                        scale=0.75,
                                        size=(0, 0),
                                        position=(self._width * 0.5,
                                                  self._height - 65),
                                        maxwidth=self._width * 0.85,
                                        h_align='center',
                                        v_align='center')

        self._scroll_width = self._width - 50
        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             size=(self._scroll_width,
                                                   self._height - 200),
                                             position=(30, 80),
                                             color=(0.4, 0.6, 0.3))
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget,
                                             border=2,
                                             margin=0)
        ba.widget(edit=self._menu_button, down_widget=self._columnwidget)

        self._muted_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height * 0.5),
            size=(0, 0),
            h_align='center',
            v_align='center',
            text=ba.Lstr(resource='chatMutedText'))
        self._chat_texts: List[ba.Widget] = []

        # add all existing messages if chat is not muted
        if not ba.app.config.resolve('Chat Muted'):
            msgs = _ba.get_chat_messages()
            for msg in msgs:
                self._add_msg(msg)

        self._text_field = txt = ba.textwidget(
            parent=self._root_widget,
            editable=True,
            size=(530, 40),
            position=(44, 39),
            text='',
            maxwidth=494,
            shadow=0.3,
            flatness=1.0,
            description=ba.Lstr(resource=self._r + '.chatMessageText'),
            autoselect=True,
            v_align='center',
            corner_scale=0.7)

        ba.widget(edit=self._scrollwidget,
                  autoselect=True,
                  left_widget=self._cancel_button,
                  up_widget=self._cancel_button,
                  down_widget=self._text_field)
        ba.widget(edit=self._columnwidget,
                  autoselect=True,
                  up_widget=self._cancel_button,
                  down_widget=self._text_field)
        ba.containerwidget(edit=self._root_widget, selected_child=txt)
        btn = ba.buttonwidget(parent=self._root_widget,
                              size=(50, 35),
                              label=ba.Lstr(resource=self._r + '.sendText'),
                              button_type='square',
                              autoselect=True,
                              position=(self._width - 70, 35),
                              on_activate_call=self._send_chat_message)
        ba.textwidget(edit=txt, on_return_press_call=btn.activate)
        self._name_widgets: List[ba.Widget] = []
        self._roster: Optional[List[Dict[str, Any]]] = None
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
        self._update()
Example #17
0
    def __init__(self,
                 position: Sequence[float] = (0.0, 1.0, 0.0),
                 velocity: Sequence[float] = (0.0, 0.0, 0.0),
                 bomb_type: str = 'normal',
                 blast_radius: float = 2.0,
                 source_player: ba.Player = None,
                 owner: ba.Node = None):
        """Create a new Bomb.

        bomb_type can be 'ice','impact','land_mine','normal','sticky', or
        'tnt'. Note that for impact or land_mine bombs you have to call arm()
        before they will go off.
        """
        super().__init__()

        factory = get_factory()

        if bomb_type not in ('ice', 'impact', 'land_mine', 'normal', 'sticky',
                             'tnt'):
            raise ValueError('invalid bomb type: ' + bomb_type)
        self.bomb_type = bomb_type

        self._exploded = False

        self.texture_sequence: Optional[ba.Node] = None

        if self.bomb_type == 'sticky':
            self._last_sticky_sound_time = 0.0

        self.blast_radius = blast_radius
        if self.bomb_type == 'ice':
            self.blast_radius *= 1.2
        elif self.bomb_type == 'impact':
            self.blast_radius *= 0.7
        elif self.bomb_type == 'land_mine':
            self.blast_radius *= 0.7
        elif self.bomb_type == 'tnt':
            self.blast_radius *= 1.45

        self._explode_callbacks: List[Callable[[Bomb, Blast], Any]] = []

        # the player this came from
        self.source_player = source_player

        # by default our hit type/subtype is our own, but we pick up types of
        # whoever sets us off so we know what caused a chain reaction
        self.hit_type = 'explosion'
        self.hit_subtype = self.bomb_type

        # if no owner was provided, use an unconnected node ref
        # (nevermind; trying to use None in these type cases instead)
        # if owner is None:
        #     owner = ba.Node(None)

        # the node this came from
        self.owner = owner

        # adding footing-materials to things can screw up jumping and flying
        # since players carrying those things
        # and thus touching footing objects will think they're on solid
        # ground.. perhaps we don't wanna add this even in the tnt case?..
        materials: Tuple[ba.Material, ...]
        if self.bomb_type == 'tnt':
            materials = (factory.bomb_material,
                         ba.sharedobj('footing_material'),
                         ba.sharedobj('object_material'))
        else:
            materials = (factory.bomb_material,
                         ba.sharedobj('object_material'))

        if self.bomb_type == 'impact':
            materials = materials + (factory.impact_blast_material, )
        elif self.bomb_type == 'land_mine':
            materials = materials + (factory.land_mine_no_explode_material, )

        if self.bomb_type == 'sticky':
            materials = materials + (factory.sticky_material, )
        else:
            materials = materials + (factory.normal_sound_material, )

        if self.bomb_type == 'land_mine':
            fuse_time = None
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': factory.land_mine_model,
                                       'light_model': factory.land_mine_model,
                                       'body': 'landMine',
                                       'shadow_size': 0.44,
                                       'color_texture': factory.land_mine_tex,
                                       'reflection': 'powerup',
                                       'reflection_scale': [1.0],
                                       'materials': materials
                                   })

        elif self.bomb_type == 'tnt':
            fuse_time = None
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': factory.tnt_model,
                                       'light_model': factory.tnt_model,
                                       'body': 'crate',
                                       'shadow_size': 0.5,
                                       'color_texture': factory.tnt_tex,
                                       'reflection': 'soft',
                                       'reflection_scale': [0.23],
                                       'materials': materials
                                   })

        elif self.bomb_type == 'impact':
            fuse_time = 20.0
            self.node = ba.newnode('prop',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'body': 'sphere',
                                       'model': factory.impact_bomb_model,
                                       'shadow_size': 0.3,
                                       'color_texture': factory.impact_tex,
                                       'reflection': 'powerup',
                                       'reflection_scale': [1.5],
                                       'materials': materials
                                   })
            self.arm_timer = ba.Timer(
                0.2, ba.WeakCall(self.handlemessage, ArmMessage()))
            self.warn_timer = ba.Timer(
                fuse_time - 1.7, ba.WeakCall(self.handlemessage,
                                             WarnMessage()))

        else:
            fuse_time = 3.0
            if self.bomb_type == 'sticky':
                sticky = True
                model = factory.sticky_bomb_model
                rtype = 'sharper'
                rscale = 1.8
            else:
                sticky = False
                model = factory.bomb_model
                rtype = 'sharper'
                rscale = 1.8
            if self.bomb_type == 'ice':
                tex = factory.ice_tex
            elif self.bomb_type == 'sticky':
                tex = factory.sticky_tex
            else:
                tex = factory.regular_tex
            self.node = ba.newnode('bomb',
                                   delegate=self,
                                   attrs={
                                       'position': position,
                                       'velocity': velocity,
                                       'model': model,
                                       'shadow_size': 0.3,
                                       'color_texture': tex,
                                       'sticky': sticky,
                                       'owner': owner,
                                       'reflection': rtype,
                                       'reflection_scale': [rscale],
                                       'materials': materials
                                   })

            sound = ba.newnode('sound',
                               owner=self.node,
                               attrs={
                                   'sound': factory.fuse_sound,
                                   'volume': 0.25
                               })
            self.node.connectattr('position', sound, 'position')
            ba.animate(self.node, 'fuse_length', {0.0: 1.0, fuse_time: 0.0})

        # Light the fuse!!!
        if self.bomb_type not in ('land_mine', 'tnt'):
            assert fuse_time is not None
            ba.timer(fuse_time,
                     ba.WeakCall(self.handlemessage, ExplodeMessage()))

        ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
Example #18
0
    def _refresh(self, select_soundtrack: str = None) -> None:
        self._allow_changing_soundtracks = False
        old_selection = self._selected_soundtrack

        # If there was no prev selection, look in prefs.
        if old_selection is None:
            old_selection = ba.app.config.get('Soundtrack')
        old_selection_index = self._selected_soundtrack_index

        # Delete old.
        while self._soundtrack_widgets:
            self._soundtrack_widgets.pop().delete()

        self._soundtracks = ba.app.config.get('Soundtracks', {})
        assert self._soundtracks is not None
        items = list(self._soundtracks.items())
        items.sort(key=lambda x: x[0].lower())
        items = [('__default__', None)] + items  # default is always first
        index = 0
        for pname, _pval in items:
            assert pname is not None
            txtw = ba.textwidget(
                parent=self._col,
                size=(self._width - 40, 24),
                text=self._get_soundtrack_display_name(pname),
                h_align='left',
                v_align='center',
                maxwidth=self._width - 110,
                always_highlight=True,
                on_select_call=ba.WeakCall(self._select, pname, index),
                on_activate_call=self._edit_soundtrack_with_sound,
                selectable=True)
            if index == 0:
                ba.widget(edit=txtw, up_widget=self._back_button)
            self._soundtrack_widgets.append(txtw)

            # Select this one if the user requested it
            if select_soundtrack is not None:
                if pname == select_soundtrack:
                    ba.columnwidget(edit=self._col,
                                    selected_child=txtw,
                                    visible_child=txtw)
            else:
                # Select this one if it was previously selected.
                # Go by index if there's one.
                if old_selection_index is not None:
                    if index == old_selection_index:
                        ba.columnwidget(edit=self._col,
                                        selected_child=txtw,
                                        visible_child=txtw)
                else:  # Otherwise look by name.
                    if pname == old_selection:
                        ba.columnwidget(edit=self._col,
                                        selected_child=txtw,
                                        visible_child=txtw)
            index += 1

        # Explicitly run select callback on current one and re-enable
        # callbacks.

        # Eww need to run this in a timer so it happens after our select
        # callbacks. With a small-enough time sometimes it happens before
        # anyway. Ew. need a way to just schedule a callable i guess.
        ba.timer(0.1,
                 ba.WeakCall(self._set_allow_changing),
                 timetype=ba.TimeType.REAL)
Example #19
0
    def __init__(self,
                 parent: ba.Widget,
                 position: Sequence[float],
                 size: Sequence[float],
                 scale: float,
                 on_activate_call: Callable[[], Any] = None,
                 transition_delay: float = None,
                 color: Sequence[float] = None,
                 textcolor: Sequence[float] = None,
                 show_tickets: bool = False,
                 button_type: str = None,
                 sale_scale: float = 1.0):
        self._position = position
        self._size = size
        self._scale = scale

        if on_activate_call is None:
            on_activate_call = ba.WeakCall(self._default_on_activate_call)
        self._on_activate_call = on_activate_call

        self._button = ba.buttonwidget(
            parent=parent,
            size=size,
            label='' if show_tickets else ba.Lstr(resource='storeText'),
            scale=scale,
            autoselect=True,
            on_activate_call=self._on_activate,
            transition_delay=transition_delay,
            color=color,
            button_type=button_type)

        self._title_text: Optional[ba.Widget]
        self._ticket_text: Optional[ba.Widget]

        if show_tickets:
            self._title_text = ba.textwidget(
                parent=parent,
                position=(position[0] + size[0] * 0.5 * scale,
                          position[1] + size[1] * 0.65 * scale),
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=size[0] * scale * 0.65,
                text=ba.Lstr(resource='storeText'),
                draw_controller=self._button,
                scale=scale,
                transition_delay=transition_delay,
                color=textcolor)
            self._ticket_text = ba.textwidget(
                parent=parent,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=size[0] * scale * 0.85,
                text='',
                color=(0.2, 1.0, 0.2),
                flatness=1.0,
                shadow=0.0,
                scale=scale * 0.6,
                transition_delay=transition_delay)
        else:
            self._title_text = None
            self._ticket_text = None

        self._circle_rad = 12 * scale
        self._circle_center = (0.0, 0.0)
        self._sale_circle_center = (0.0, 0.0)

        self._available_purchase_backing = ba.imagewidget(
            parent=parent,
            color=(1, 0, 0),
            draw_controller=self._button,
            size=(2.2 * self._circle_rad, 2.2 * self._circle_rad),
            texture=ba.gettexture('circleShadow'),
            transition_delay=transition_delay)
        self._available_purchase_text = ba.textwidget(
            parent=parent,
            size=(0, 0),
            h_align='center',
            v_align='center',
            text='',
            draw_controller=self._button,
            color=(1, 1, 1),
            flatness=1.0,
            shadow=1.0,
            scale=0.6 * scale,
            maxwidth=self._circle_rad * 1.4,
            transition_delay=transition_delay)

        self._sale_circle_rad = 18 * scale * sale_scale
        self._sale_backing = ba.imagewidget(
            parent=parent,
            color=(0.5, 0, 1.0),
            draw_controller=self._button,
            size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad),
            texture=ba.gettexture('circleZigZag'),
            transition_delay=transition_delay)
        self._sale_title_text = ba.textwidget(
            parent=parent,
            size=(0, 0),
            h_align='center',
            v_align='center',
            draw_controller=self._button,
            color=(0, 1, 0),
            flatness=1.0,
            shadow=0.0,
            scale=0.5 * scale * sale_scale,
            maxwidth=self._sale_circle_rad * 1.5,
            transition_delay=transition_delay)
        self._sale_time_text = ba.textwidget(parent=parent,
                                             size=(0, 0),
                                             h_align='center',
                                             v_align='center',
                                             draw_controller=self._button,
                                             color=(0, 1, 0),
                                             flatness=1.0,
                                             shadow=0.0,
                                             scale=0.4 * scale * sale_scale,
                                             maxwidth=self._sale_circle_rad *
                                             1.5,
                                             transition_delay=transition_delay)

        self.set_position(position)
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
        self._update()
Example #20
0
    def __init__(self,
                 existing_profile: Optional[str],
                 in_main_menu: bool,
                 transition: str = 'in_right'):
        # FIXME: Tidy this up a bit.
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import get_player_profile_colors
        self._in_main_menu = in_main_menu
        self._existing_profile = existing_profile
        self._r = 'editProfileWindow'
        self._spazzes: List[str] = []
        self._icon_textures: List[ba.Texture] = []
        self._icon_tint_textures: List[ba.Texture] = []

        # Grab profile colors or pick random ones.
        self._color, self._highlight = get_player_profile_colors(
            existing_profile)
        self._width = width = 780.0 if ba.app.small_ui else 680.0
        self._x_inset = x_inset = 50.0 if ba.app.small_ui else 0.0
        self._height = height = (350.0 if ba.app.small_ui else
                                 400.0 if ba.app.med_ui else 450.0)
        spacing = 40
        self._base_scale = (2.05 if ba.app.small_ui else
                            1.5 if ba.app.med_ui else 1.0)
        top_extra = 15 if ba.app.small_ui else 15
        super().__init__(root_widget=ba.containerwidget(
            size=(width, height + top_extra),
            transition=transition,
            scale=self._base_scale,
            stack_offset=(0, 15) if ba.app.small_ui else (0, 0)))
        cancel_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(52 + x_inset, height - 60),
            size=(155, 60),
            scale=0.8,
            autoselect=True,
            label=ba.Lstr(resource='cancelText'),
            on_activate_call=self._cancel)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)
        save_button = btn = ba.buttonwidget(parent=self._root_widget,
                                            position=(width - (177 + x_inset),
                                                      height - 60),
                                            size=(155, 60),
                                            autoselect=True,
                                            scale=0.8,
                                            label=ba.Lstr(resource='saveText'))
        ba.widget(edit=save_button, left_widget=cancel_button)
        ba.widget(edit=cancel_button, right_widget=save_button)
        ba.containerwidget(edit=self._root_widget, start_button=btn)
        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, height - 38),
                      size=(0, 0),
                      text=(ba.Lstr(resource=self._r + '.titleNewText')
                            if existing_profile is None else ba.Lstr(
                                resource=self._r + '.titleEditText')),
                      color=ba.app.title_color,
                      maxwidth=290,
                      scale=1.0,
                      h_align="center",
                      v_align="center")

        # Make a list of spaz icons.
        self.refresh_characters()
        profile = ba.app.config.get('Player Profiles',
                                    {}).get(self._existing_profile, {})

        if 'global' in profile:
            self._global = profile['global']
        else:
            self._global = False

        if 'icon' in profile:
            self._icon = profile['icon']
        else:
            self._icon = ba.charstr(ba.SpecialChar.LOGO)

        assigned_random_char = False

        # Look for existing character choice or pick random one otherwise.
        try:
            icon_index = self._spazzes.index(profile['character'])
        except Exception:
            # Let's set the default icon to spaz for our first profile; after
            # that we go random.
            # (SCRATCH THAT.. we now hard-code account-profiles to start with
            # spaz which has a similar effect)
            # try: p_len = len(ba.app.config['Player Profiles'])
            # except Exception: p_len = 0
            # if p_len == 0: icon_index = self._spazzes.index('Spaz')
            # else:
            random.seed()
            icon_index = random.randrange(len(self._spazzes))
            assigned_random_char = True
        self._icon_index = icon_index
        ba.buttonwidget(edit=save_button, on_activate_call=self.save)

        v = height - 115.0
        self._name = ('' if self._existing_profile is None else
                      self._existing_profile)
        self._is_account_profile = (self._name == '__account__')

        # If we just picked a random character, see if it has specific
        # colors/highlights associated with it and assign them if so.
        if assigned_random_char:
            clr = ba.app.spaz_appearances[
                self._spazzes[icon_index]].default_color
            if clr is not None:
                self._color = clr
            highlight = ba.app.spaz_appearances[
                self._spazzes[icon_index]].default_highlight
            if highlight is not None:
                self._highlight = highlight

        # Assign a random name if they had none.
        if self._name == '':
            names = _ba.get_random_names()
            self._name = names[random.randrange(len(names))]

        self._clipped_name_text = ba.textwidget(parent=self._root_widget,
                                                text='',
                                                position=(540 + x_inset,
                                                          v - 8),
                                                flatness=1.0,
                                                shadow=0.0,
                                                scale=0.55,
                                                size=(0, 0),
                                                maxwidth=100,
                                                h_align='center',
                                                v_align='center',
                                                color=(1, 1, 0, 0.5))

        if not self._is_account_profile and not self._global:
            ba.textwidget(parent=self._root_widget,
                          text=ba.Lstr(resource=self._r + '.nameText'),
                          position=(200 + x_inset, v - 6),
                          size=(0, 0),
                          h_align='right',
                          v_align='center',
                          color=(1, 1, 1, 0.5),
                          scale=0.9)

        self._upgrade_button = None
        if self._is_account_profile:
            if _ba.get_account_state() == 'signed_in':
                sval = _ba.get_account_display_string()
            else:
                sval = '??'
            ba.textwidget(parent=self._root_widget,
                          position=(self._width * 0.5, v - 7),
                          size=(0, 0),
                          scale=1.2,
                          text=sval,
                          maxwidth=270,
                          h_align='center',
                          v_align='center')
            txtl = ba.Lstr(
                resource='editProfileWindow.accountProfileText').evaluate()
            b_width = min(
                270.0,
                _ba.get_string_width(txtl, suppress_warning=True) * 0.6)
            ba.textwidget(parent=self._root_widget,
                          position=(self._width * 0.5, v - 39),
                          size=(0, 0),
                          scale=0.6,
                          color=ba.app.infotextcolor,
                          text=txtl,
                          maxwidth=270,
                          h_align='center',
                          v_align='center')
            self._account_type_info_button = ba.buttonwidget(
                parent=self._root_widget,
                label='?',
                size=(15, 15),
                text_scale=0.6,
                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47),
                button_type='square',
                color=(0.6, 0.5, 0.65),
                autoselect=True,
                on_activate_call=self.show_account_profile_info)
        elif self._global:

            b_size = 60
            self._icon_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                autoselect=True,
                position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15),
                size=(b_size, b_size),
                color=(0.6, 0.5, 0.6),
                label='',
                button_type='square',
                text_scale=1.2,
                on_activate_call=self._on_icon_press)
            self._icon_button_label = ba.textwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 - 160, v - 35),
                draw_controller=btn,
                h_align='center',
                v_align='center',
                size=(0, 0),
                color=(1, 1, 1),
                text='',
                scale=2.0)

            ba.textwidget(parent=self._root_widget,
                          h_align='center',
                          v_align='center',
                          position=(self._width * 0.5 - 160, v - 55 - 15),
                          size=(0, 0),
                          draw_controller=btn,
                          text=ba.Lstr(resource=self._r + '.iconText'),
                          scale=0.7,
                          color=ba.app.title_color,
                          maxwidth=120)

            self._update_icon()

            ba.textwidget(parent=self._root_widget,
                          position=(self._width * 0.5, v - 7),
                          size=(0, 0),
                          scale=1.2,
                          text=self._name,
                          maxwidth=240,
                          h_align='center',
                          v_align='center')
            # FIXME hard coded strings are bad
            txtl = ba.Lstr(
                resource='editProfileWindow.globalProfileText').evaluate()
            b_width = min(
                240.0,
                _ba.get_string_width(txtl, suppress_warning=True) * 0.6)
            ba.textwidget(parent=self._root_widget,
                          position=(self._width * 0.5, v - 39),
                          size=(0, 0),
                          scale=0.6,
                          color=ba.app.infotextcolor,
                          text=txtl,
                          maxwidth=240,
                          h_align='center',
                          v_align='center')
            self._account_type_info_button = ba.buttonwidget(
                parent=self._root_widget,
                label='?',
                size=(15, 15),
                text_scale=0.6,
                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47),
                button_type='square',
                color=(0.6, 0.5, 0.65),
                autoselect=True,
                on_activate_call=self.show_global_profile_info)
        else:
            self._text_field = ba.textwidget(
                parent=self._root_widget,
                position=(220 + x_inset, v - 30),
                size=(265, 40),
                text=self._name,
                h_align='left',
                v_align='center',
                max_chars=16,
                description=ba.Lstr(resource=self._r + '.nameDescriptionText'),
                autoselect=True,
                editable=True,
                padding=4,
                color=(0.9, 0.9, 0.9, 1.0),
                on_return_press_call=ba.Call(save_button.activate))

            # FIXME hard coded strings are bad
            txtl = ba.Lstr(
                resource='editProfileWindow.localProfileText').evaluate()
            b_width = min(
                270.0,
                _ba.get_string_width(txtl, suppress_warning=True) * 0.6)
            ba.textwidget(parent=self._root_widget,
                          position=(self._width * 0.5, v - 43),
                          size=(0, 0),
                          scale=0.6,
                          color=ba.app.infotextcolor,
                          text=txtl,
                          maxwidth=270,
                          h_align='center',
                          v_align='center')
            self._account_type_info_button = ba.buttonwidget(
                parent=self._root_widget,
                label='?',
                size=(15, 15),
                text_scale=0.6,
                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50),
                button_type='square',
                color=(0.6, 0.5, 0.65),
                autoselect=True,
                on_activate_call=self.show_local_profile_info)
            self._upgrade_button = ba.buttonwidget(
                parent=self._root_widget,
                label=ba.Lstr(resource='upgradeText'),
                size=(40, 17),
                text_scale=1.0,
                button_type='square',
                position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51),
                color=(0.6, 0.5, 0.65),
                autoselect=True,
                on_activate_call=self.upgrade_profile)

        self._update_clipped_name()
        self._clipped_name_timer = ba.Timer(0.333,
                                            ba.WeakCall(
                                                self._update_clipped_name),
                                            timetype=ba.TimeType.REAL,
                                            repeat=True)

        v -= spacing * 3.0
        b_size = 80
        b_size_2 = 100
        b_offs = 150
        self._color_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50),
            size=(b_size, b_size),
            color=self._color,
            label='',
            button_type='square')
        origin = self._color_button.get_screen_space_center()
        ba.buttonwidget(edit=self._color_button,
                        on_activate_call=ba.WeakCall(self._make_picker,
                                                     'color', origin))
        ba.textwidget(parent=self._root_widget,
                      h_align='center',
                      v_align='center',
                      position=(self._width * 0.5 - b_offs, v - 65),
                      size=(0, 0),
                      draw_controller=btn,
                      text=ba.Lstr(resource=self._r + '.colorText'),
                      scale=0.7,
                      color=ba.app.title_color,
                      maxwidth=120)

        self._character_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(self._width * 0.5 - b_size_2 * 0.5, v - 60),
            up_widget=self._account_type_info_button,
            on_activate_call=self._on_character_press,
            size=(b_size_2, b_size_2),
            label='',
            color=(1, 1, 1),
            mask_texture=ba.gettexture('characterIconMask'))
        if not self._is_account_profile and not self._global:
            ba.containerwidget(edit=self._root_widget,
                               selected_child=self._text_field)
        ba.textwidget(parent=self._root_widget,
                      h_align='center',
                      v_align='center',
                      position=(self._width * 0.5, v - 80),
                      size=(0, 0),
                      draw_controller=btn,
                      text=ba.Lstr(resource=self._r + '.characterText'),
                      scale=0.7,
                      color=ba.app.title_color,
                      maxwidth=130)

        self._highlight_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50),
            up_widget=self._upgrade_button if self._upgrade_button is not None
            else self._account_type_info_button,
            size=(b_size, b_size),
            color=self._highlight,
            label='',
            button_type='square')

        if not self._is_account_profile and not self._global:
            ba.widget(edit=cancel_button, down_widget=self._text_field)
            ba.widget(edit=save_button, down_widget=self._text_field)
            ba.widget(edit=self._color_button, up_widget=self._text_field)
        ba.widget(edit=self._account_type_info_button,
                  down_widget=self._character_button)

        origin = self._highlight_button.get_screen_space_center()
        ba.buttonwidget(edit=self._highlight_button,
                        on_activate_call=ba.WeakCall(self._make_picker,
                                                     'highlight', origin))
        ba.textwidget(parent=self._root_widget,
                      h_align='center',
                      v_align='center',
                      position=(self._width * 0.5 + b_offs, v - 65),
                      size=(0, 0),
                      draw_controller=btn,
                      text=ba.Lstr(resource=self._r + '.highlightText'),
                      scale=0.7,
                      color=ba.app.title_color,
                      maxwidth=120)
        self._update_character()
Example #21
0
    def __init__(self,
                 parent: ba.Widget,
                 position: Tuple[float, float],
                 initial_color: Sequence[float] = (1.0, 1.0, 1.0),
                 delegate: Any = None,
                 scale: float = None,
                 offset: Tuple[float, float] = (0.0, 0.0),
                 tag: Any = ''):
        # pylint: disable=too-many-locals
        from ba.internal import have_pro, get_player_colors

        c_raw = get_player_colors()
        assert len(c_raw) == 16
        self.colors = [c_raw[0:4], c_raw[4:8], c_raw[8:12], c_raw[12:16]]

        uiscale = ba.app.uiscale
        if scale is None:
            scale = (2.3 if uiscale is ba.UIScale.SMALL else
                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
        self._parent = parent
        self._position = position
        self._scale = scale
        self._offset = offset
        self._delegate = delegate
        self._transitioning_out = False
        self._tag = tag
        self._initial_color = initial_color

        # Create our _root_widget.
        PopupWindow.__init__(self,
                             position=position,
                             size=(210, 240),
                             scale=scale,
                             focus_position=(10, 10),
                             focus_size=(190, 220),
                             bg_color=(0.5, 0.5, 0.5),
                             offset=offset)
        rows: List[List[ba.Widget]] = []
        closest_dist = 9999.0
        closest = (0, 0)
        for y in range(4):
            row: List[ba.Widget] = []
            rows.append(row)
            for x in range(4):
                color = self.colors[y][x]
                dist = (abs(color[0] - initial_color[0]) +
                        abs(color[1] - initial_color[1]) +
                        abs(color[2] - initial_color[2]))
                if dist < closest_dist:
                    closest = (x, y)
                    closest_dist = dist
                btn = ba.buttonwidget(parent=self.root_widget,
                                      position=(22 + 45 * x, 185 - 45 * y),
                                      size=(35, 40),
                                      label='',
                                      button_type='square',
                                      on_activate_call=ba.WeakCall(
                                          self._select, x, y),
                                      autoselect=True,
                                      color=color,
                                      extra_touch_border_scale=0.0)
                row.append(btn)
        other_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(105 - 60, 13),
            color=(0.7, 0.7, 0.7),
            text_scale=0.5,
            textcolor=(0.8, 0.8, 0.8),
            size=(120, 30),
            label=ba.Lstr(resource='otherText',
                          fallback_resource='coopSelectWindow.customText'),
            autoselect=True,
            on_activate_call=ba.WeakCall(self._select_other))

        # Custom colors are limited to pro currently.
        if not have_pro():
            ba.imagewidget(parent=self.root_widget,
                           position=(50, 12),
                           size=(30, 30),
                           texture=ba.gettexture('lock'),
                           draw_controller=other_button)

        # If their color is close to one of our swatches, select it.
        # Otherwise select 'other'.
        if closest_dist < 0.03:
            ba.containerwidget(edit=self.root_widget,
                               selected_child=rows[closest[1]][closest[0]])
        else:
            ba.containerwidget(edit=self.root_widget,
                               selected_child=other_button)
Example #22
0
    def __init__(self, queue_id: str, address: str, port: int):
        ba.app.ui.have_party_queue_window = True
        self._address = address
        self._port = port
        self._queue_id = queue_id
        self._width = 800
        self._height = 400
        self._last_connect_attempt_time: Optional[float] = None
        self._last_transaction_time: Optional[float] = None
        self._boost_button: Optional[ba.Widget] = None
        self._boost_price: Optional[ba.Widget] = None
        self._boost_label: Optional[ba.Widget] = None
        self._field_shown = False
        self._dudes: list[PartyQueueWindow.Dude] = []
        self._dudes_by_id: dict[int, PartyQueueWindow.Dude] = {}
        self._line_left = 40.0
        self._line_width = self._width - 190
        self._line_bottom = self._height * 0.4
        self.lineup_tex = ba.gettexture('playerLineup')
        self._smoothing = 0.0
        self._initial_offset = 0.0
        self._boost_tickets = 0
        self._boost_strength = 0.0
        self._angry_computer_transparent_model = ba.getmodel(
            'angryComputerTransparent')
        self._angry_computer_image: Optional[ba.Widget] = None
        self.lineup_1_transparent_model = ba.getmodel(
            'playerLineup1Transparent')
        self._lineup_2_transparent_model = ba.getmodel(
            'playerLineup2Transparent')
        self._lineup_3_transparent_model = ba.getmodel(
            'playerLineup3Transparent')
        self._lineup_4_transparent_model = ba.getmodel(
            'playerLineup4Transparent')
        self._line_image: Optional[ba.Widget] = None
        self.eyes_model = ba.getmodel('plasticEyesTransparent')
        self._white_tex = ba.gettexture('white')
        uiscale = ba.app.ui.uiscale
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            color=(0.45, 0.63, 0.15),
            transition='in_scale',
            scale=(1.4 if uiscale is ba.UIScale.SMALL else
                   1.2 if uiscale is ba.UIScale.MEDIUM else 1.0)))

        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              scale=1.0,
                                              position=(60, self._height - 80),
                                              size=(50, 50),
                                              label='',
                                              on_activate_call=self.close,
                                              autoselect=True,
                                              color=(0.45, 0.63, 0.15),
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)

        self._title_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height * 0.55),
            size=(0, 0),
            color=(1.0, 3.0, 1.0),
            scale=1.3,
            h_align='center',
            v_align='center',
            text=ba.Lstr(resource='internal.connectingToPartyText'),
            maxwidth=self._width * 0.65)

        self._tickets_text = ba.textwidget(parent=self._root_widget,
                                           position=(self._width - 180,
                                                     self._height - 20),
                                           size=(0, 0),
                                           color=(0.2, 1.0, 0.2),
                                           scale=0.7,
                                           h_align='center',
                                           v_align='center',
                                           text='')

        # update at roughly 30fps
        self._update_timer = ba.Timer(0.033,
                                      ba.WeakCall(self.update),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
        self.update()
    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)
Example #24
0
        def __init__(self, parent: PartyQueueWindow, distance: float,
                     initial_offset: float, is_player: bool, account_id: str,
                     name: str):
            self.claimed = False
            self._line_left = parent.get_line_left()
            self._line_width = parent.get_line_width()
            self._line_bottom = parent.get_line_bottom()
            self._target_distance = distance
            self._distance = distance + initial_offset
            self._boost_brightness = 0.0
            self._debug = False
            self._sc = sc = 1.1 if is_player else 0.6 + random.random() * 0.2
            self._y_offs = -30.0 if is_player else -47.0 * sc
            self._last_boost_time = 0.0
            self._color = (0.2, 1.0,
                           0.2) if is_player else (0.5 + 0.3 * random.random(),
                                                   0.4 + 0.2 * random.random(),
                                                   0.5 + 0.3 * random.random())
            self._eye_color = (0.7 * 1.0 + 0.3 * self._color[0],
                               0.7 * 1.0 + 0.3 * self._color[1],
                               0.7 * 1.0 + 0.3 * self._color[2])
            self._body_image = ba.buttonwidget(
                parent=parent.get_root_widget(),
                selectable=True,
                label='',
                size=(sc * 60, sc * 80),
                color=self._color,
                texture=parent.lineup_tex,
                model_transparent=parent.lineup_1_transparent_model)
            ba.buttonwidget(edit=self._body_image,
                            on_activate_call=ba.WeakCall(
                                parent.on_account_press, account_id,
                                self._body_image))
            ba.widget(edit=self._body_image, autoselect=True)
            self._eyes_image = ba.imagewidget(
                parent=parent.get_root_widget(),
                size=(sc * 36, sc * 18),
                texture=parent.lineup_tex,
                color=self._eye_color,
                model_transparent=parent.eyes_model)
            self._name_text = ba.textwidget(parent=parent.get_root_widget(),
                                            size=(0, 0),
                                            shadow=0,
                                            flatness=1.0,
                                            text=name,
                                            maxwidth=100,
                                            h_align='center',
                                            v_align='center',
                                            scale=0.75,
                                            color=(1, 1, 1, 0.6))
            self._update_image()

            # DEBUG: vis target pos..
            self._body_image_target: Optional[ba.Widget]
            self._eyes_image_target: Optional[ba.Widget]
            if self._debug:
                self._body_image_target = ba.imagewidget(
                    parent=parent.get_root_widget(),
                    size=(sc * 60, sc * 80),
                    color=self._color,
                    texture=parent.lineup_tex,
                    model_transparent=parent.lineup_1_transparent_model)
                self._eyes_image_target = ba.imagewidget(
                    parent=parent.get_root_widget(),
                    size=(sc * 36, sc * 18),
                    texture=parent.lineup_tex,
                    color=self._eye_color,
                    model_transparent=parent.eyes_model)
                # (updates our image positions)
                self.set_target_distance(self._target_distance)
            else:
                self._body_image_target = self._eyes_image_target = None
Example #25
0
    def on_begin(self) -> None:
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        from bastd.actor.text import Text
        from bastd.actor.image import Image
        from ba.deprecated import get_resource
        ba.set_analytics_screen('FreeForAll Series Victory Screen' if self.
                                _is_ffa else 'Teams Series Victory Screen')
        if ba.app.uiscale is ba.UIScale.LARGE:
            sval = ba.Lstr(resource='pressAnyKeyButtonPlayAgainText')
        else:
            sval = ba.Lstr(resource='pressAnyButtonPlayAgainText')
        self._show_up_next = False
        self._custom_continue_message = sval
        super().on_begin()
        winning_sessionteam = self.settings_raw['winner']

        # Pause a moment before playing victory music.
        ba.timer(0.6, ba.WeakCall(self._play_victory_music))
        ba.timer(4.4,
                 ba.WeakCall(self._show_winner, self.settings_raw['winner']))
        ba.timer(4.6, ba.Call(ba.playsound, self._score_display_sound))

        # Score / Name / Player-record.
        player_entries: List[Tuple[int, str, ba.PlayerRecord]] = []

        # Note: for ffa, exclude players who haven't entered the game yet.
        if self._is_ffa:
            for _pkey, prec in self.stats.get_records().items():
                if prec.player.in_game:
                    player_entries.append(
                        (prec.player.sessionteam.customdata['score'],
                         prec.getname(full=True), prec))
            player_entries.sort(reverse=True, key=lambda x: x[0])
        else:
            for _pkey, prec in self.stats.get_records().items():
                player_entries.append((prec.score, prec.name_full, prec))
            player_entries.sort(reverse=True, key=lambda x: x[0])

        ts_height = 300.0
        ts_h_offs = -390.0
        tval = 6.4
        t_incr = 0.12

        always_use_first_to = get_resource('bestOfUseFirstToInstead')

        session = self.session
        if self._is_ffa:
            assert isinstance(session, ba.FreeForAllSession)
            txt = ba.Lstr(
                value='${A}:',
                subs=[('${A}',
                       ba.Lstr(resource='firstToFinalText',
                               subs=[('${COUNT}',
                                      str(session.get_ffa_series_length()))]))
                      ])
        else:
            assert isinstance(session, ba.MultiTeamSession)

            # Some languages may prefer to always show 'first to X' instead of
            # 'best of X'.
            # FIXME: This will affect all clients connected to us even if
            #  they're not using this language. Should try to come up
            #  with a wording that works everywhere.
            if always_use_first_to:
                txt = ba.Lstr(
                    value='${A}:',
                    subs=[
                        ('${A}',
                         ba.Lstr(resource='firstToFinalText',
                                 subs=[
                                     ('${COUNT}',
                                      str(session.get_series_length() / 2 + 1))
                                 ]))
                    ])
            else:
                txt = ba.Lstr(
                    value='${A}:',
                    subs=[('${A}',
                           ba.Lstr(resource='bestOfFinalText',
                                   subs=[('${COUNT}',
                                          str(session.get_series_length()))]))
                          ])

        Text(txt,
             v_align=Text.VAlign.CENTER,
             maxwidth=300,
             color=(0.5, 0.5, 0.5, 1.0),
             position=(0, 220),
             scale=1.2,
             transition=Text.Transition.IN_TOP_SLOW,
             h_align=Text.HAlign.CENTER,
             transition_delay=t_incr * 4).autoretain()

        win_score = (session.get_series_length() - 1) // 2 + 1
        lose_score = 0
        for team in self.teams:
            if team.sessionteam.customdata['score'] != win_score:
                lose_score = team.sessionteam.customdata['score']

        if not self._is_ffa:
            Text(ba.Lstr(resource='gamesToText',
                         subs=[('${WINCOUNT}', str(win_score)),
                               ('${LOSECOUNT}', str(lose_score))]),
                 color=(0.5, 0.5, 0.5, 1.0),
                 maxwidth=160,
                 v_align=Text.VAlign.CENTER,
                 position=(0, -215),
                 scale=1.8,
                 transition=Text.Transition.IN_LEFT,
                 h_align=Text.HAlign.CENTER,
                 transition_delay=4.8 + t_incr * 4).autoretain()

        if self._is_ffa:
            v_extra = 120
        else:
            v_extra = 0

        mvp: Optional[ba.PlayerRecord] = None
        mvp_name: Optional[str] = None

        # Show game MVP.
        if not self._is_ffa:
            mvp, mvp_name = None, None
            for entry in player_entries:
                if entry[2].team == winning_sessionteam:
                    mvp = entry[2]
                    mvp_name = entry[1]
                    break
            if mvp is not None:
                Text(ba.Lstr(resource='mostValuablePlayerText'),
                     color=(0.5, 0.5, 0.5, 1.0),
                     v_align=Text.VAlign.CENTER,
                     maxwidth=300,
                     position=(180, ts_height / 2 + 15),
                     transition=Text.Transition.IN_LEFT,
                     h_align=Text.HAlign.LEFT,
                     transition_delay=tval).autoretain()
                tval += 4 * t_incr

                Image(mvp.get_icon(),
                      position=(230, ts_height / 2 - 55 + 14 - 5),
                      scale=(70, 70),
                      transition=Image.Transition.IN_LEFT,
                      transition_delay=tval).autoretain()
                assert mvp_name is not None
                Text(ba.Lstr(value=mvp_name),
                     position=(280, ts_height / 2 - 55 + 15 - 5),
                     h_align=Text.HAlign.LEFT,
                     v_align=Text.VAlign.CENTER,
                     maxwidth=170,
                     scale=1.3,
                     color=ba.safecolor(mvp.team.color + (1, )),
                     transition=Text.Transition.IN_LEFT,
                     transition_delay=tval).autoretain()
                tval += 4 * t_incr

        # Most violent.
        most_kills = 0
        for entry in player_entries:
            if entry[2].kill_count >= most_kills:
                mvp = entry[2]
                mvp_name = entry[1]
                most_kills = entry[2].kill_count
        if mvp is not None:
            Text(ba.Lstr(resource='mostViolentPlayerText'),
                 color=(0.5, 0.5, 0.5, 1.0),
                 v_align=Text.VAlign.CENTER,
                 maxwidth=300,
                 position=(180, ts_height / 2 - 150 + v_extra + 15),
                 transition=Text.Transition.IN_LEFT,
                 h_align=Text.HAlign.LEFT,
                 transition_delay=tval).autoretain()
            Text(ba.Lstr(value='(${A})',
                         subs=[('${A}',
                                ba.Lstr(resource='killsTallyText',
                                        subs=[('${COUNT}', str(most_kills))]))
                               ]),
                 position=(260, ts_height / 2 - 150 - 15 + v_extra),
                 color=(0.3, 0.3, 0.3, 1.0),
                 scale=0.6,
                 h_align=Text.HAlign.LEFT,
                 transition=Text.Transition.IN_LEFT,
                 transition_delay=tval).autoretain()
            tval += 4 * t_incr

            Image(mvp.get_icon(),
                  position=(233, ts_height / 2 - 150 - 30 - 46 + 25 + v_extra),
                  scale=(50, 50),
                  transition=Image.Transition.IN_LEFT,
                  transition_delay=tval).autoretain()
            assert mvp_name is not None
            Text(ba.Lstr(value=mvp_name),
                 position=(270, ts_height / 2 - 150 - 30 - 36 + v_extra + 15),
                 h_align=Text.HAlign.LEFT,
                 v_align=Text.VAlign.CENTER,
                 maxwidth=180,
                 color=ba.safecolor(mvp.team.color + (1, )),
                 transition=Text.Transition.IN_LEFT,
                 transition_delay=tval).autoretain()
            tval += 4 * t_incr

        # Most killed.
        most_killed = 0
        mkp, mkp_name = None, None
        for entry in player_entries:
            if entry[2].killed_count >= most_killed:
                mkp = entry[2]
                mkp_name = entry[1]
                most_killed = entry[2].killed_count
        if mkp is not None:
            Text(ba.Lstr(resource='mostViolatedPlayerText'),
                 color=(0.5, 0.5, 0.5, 1.0),
                 v_align=Text.VAlign.CENTER,
                 maxwidth=300,
                 position=(180, ts_height / 2 - 300 + v_extra + 15),
                 transition=Text.Transition.IN_LEFT,
                 h_align=Text.HAlign.LEFT,
                 transition_delay=tval).autoretain()
            Text(ba.Lstr(value='(${A})',
                         subs=[('${A}',
                                ba.Lstr(resource='deathsTallyText',
                                        subs=[('${COUNT}', str(most_killed))]))
                               ]),
                 position=(260, ts_height / 2 - 300 - 15 + v_extra),
                 h_align=Text.HAlign.LEFT,
                 scale=0.6,
                 color=(0.3, 0.3, 0.3, 1.0),
                 transition=Text.Transition.IN_LEFT,
                 transition_delay=tval).autoretain()
            tval += 4 * t_incr
            Image(mkp.get_icon(),
                  position=(233, ts_height / 2 - 300 - 30 - 46 + 25 + v_extra),
                  scale=(50, 50),
                  transition=Image.Transition.IN_LEFT,
                  transition_delay=tval).autoretain()
            assert mkp_name is not None
            Text(ba.Lstr(value=mkp_name),
                 position=(270, ts_height / 2 - 300 - 30 - 36 + v_extra + 15),
                 h_align=Text.HAlign.LEFT,
                 v_align=Text.VAlign.CENTER,
                 color=ba.safecolor(mkp.team.color + (1, )),
                 maxwidth=180,
                 transition=Text.Transition.IN_LEFT,
                 transition_delay=tval).autoretain()
            tval += 4 * t_incr

        # Now show individual scores.
        tdelay = tval
        Text(ba.Lstr(resource='finalScoresText'),
             color=(0.5, 0.5, 0.5, 1.0),
             position=(ts_h_offs, ts_height / 2),
             transition=Text.Transition.IN_RIGHT,
             transition_delay=tdelay).autoretain()
        tdelay += 4 * t_incr

        v_offs = 0.0
        tdelay += len(player_entries) * 8 * t_incr
        for _score, name, prec in player_entries:
            tdelay -= 4 * t_incr
            v_offs -= 40
            Text(str(prec.team.customdata['score'])
                 if self._is_ffa else str(prec.score),
                 color=(0.5, 0.5, 0.5, 1.0),
                 position=(ts_h_offs + 230, ts_height / 2 + v_offs),
                 h_align=Text.HAlign.RIGHT,
                 transition=Text.Transition.IN_RIGHT,
                 transition_delay=tdelay).autoretain()
            tdelay -= 4 * t_incr

            Image(prec.get_icon(),
                  position=(ts_h_offs - 72, ts_height / 2 + v_offs + 15),
                  scale=(30, 30),
                  transition=Image.Transition.IN_LEFT,
                  transition_delay=tdelay).autoretain()
            Text(ba.Lstr(value=name),
                 position=(ts_h_offs - 50, ts_height / 2 + v_offs + 15),
                 h_align=Text.HAlign.LEFT,
                 v_align=Text.VAlign.CENTER,
                 maxwidth=180,
                 color=ba.safecolor(prec.team.color + (1, )),
                 transition=Text.Transition.IN_RIGHT,
                 transition_delay=tdelay).autoretain()

        ba.timer(15.0, ba.WeakCall(self._show_tips))
Example #26
0
    def __init__(self,
                 sessiontype: Type[ba.Session],
                 transition: str = 'in_right',
                 select_playlist: str = None,
                 origin_widget: ba.Widget = None):
        # Yes this needs tidying.
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        # pylint: disable=cyclic-import
        from bastd.ui import playlist
        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._sessiontype = sessiontype
        self._pvars = playlist.PlaylistTypeVars(sessiontype)
        self._max_playlists = 30
        self._r = 'gameListWindow'
        self._width = 750.0 if ba.app.small_ui else 650.0
        x_inset = 50.0 if ba.app.small_ui else 0.0
        self._height = (380.0 if ba.app.small_ui else
                        420.0 if ba.app.med_ui else 500.0)
        top_extra = 20.0 if ba.app.small_ui else 0.0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(2.05 if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0),
            stack_offset=(0, -10) if ba.app.small_ui else (0, 0)))

        self._back_button = back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(43 + x_inset, self._height - 60),
            size=(160, 68),
            scale=0.77,
            autoselect=True,
            text_scale=1.3,
            label=ba.Lstr(resource='backText'),
            button_type='back')

        ba.textwidget(parent=self._root_widget,
                      position=(0, self._height - 47),
                      size=(self._width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText',
                                   subs=[('${TYPE}',
                                          self._pvars.window_title_name)]),
                      color=ba.app.heading_color,
                      maxwidth=290,
                      h_align='center',
                      v_align='center')

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

        v = self._height - 59.0
        h = 41 + x_inset
        b_color = (0.6, 0.53, 0.63)
        b_textcolor = (0.75, 0.7, 0.8)
        self._lock_images: List[ba.Widget] = []
        lock_tex = ba.gettexture('lock')

        scl = (1.1 if ba.app.small_ui else 1.27 if ba.app.med_ui else 1.57)
        scl *= 0.63
        v -= 65.0 * scl
        new_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._new_playlist,
            color=b_color,
            autoselect=True,
            button_type='square',
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource='newText',
                          fallback_resource=self._r + '.newText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        self._edit_button = edit_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._edit_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='editText',
                          fallback_resource=self._r + '.editText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        duplicate_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._duplicate_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='duplicateText',
                          fallback_resource=self._r + '.duplicateText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        delete_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._delete_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='deleteText',
                          fallback_resource=self._r + '.deleteText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))
        v -= 65.0 * scl
        self._import_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._import_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='importText'))
        v -= 65.0 * scl
        btn = ba.buttonwidget(parent=self._root_widget,
                              position=(h, v),
                              size=(90, 58.0 * scl),
                              on_activate_call=self._share_playlist,
                              color=b_color,
                              autoselect=True,
                              textcolor=b_textcolor,
                              button_type='square',
                              text_scale=0.7,
                              label=ba.Lstr(resource='shareText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v = self._height - 75
        self._scroll_height = self._height - 119
        scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                       position=(140 + x_inset,
                                                 v - self._scroll_height),
                                       size=(self._width - (180 + 2 * x_inset),
                                             self._scroll_height + 10),
                                       highlight=False)
        ba.widget(edit=back_button, right_widget=scrollwidget)
        self._columnwidget = ba.columnwidget(parent=scrollwidget)

        h = 145

        try:
            self._do_randomize_val = ba.app.config[self._pvars.config_name +
                                                   ' Playlist Randomize']
        except Exception:
            self._do_randomize_val = 0

        h += 210

        for btn in [new_button, delete_button, edit_button, duplicate_button]:
            ba.widget(edit=btn, right_widget=scrollwidget)
        ba.widget(edit=scrollwidget,
                  left_widget=new_button,
                  right_widget=_ba.get_special_widget('party_button')
                  if ba.app.toolbars else None)

        # make sure config exists
        self._config_name_full = self._pvars.config_name + ' Playlists'

        if self._config_name_full not in ba.app.config:
            ba.app.config[self._config_name_full] = {}

        self._selected_playlist_name: Optional[str] = None
        self._selected_playlist_index: Optional[int] = None
        self._playlist_widgets: List[ba.Widget] = []

        self._refresh(select_playlist=select_playlist)

        ba.buttonwidget(edit=back_button, on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=back_button)

        ba.containerwidget(edit=self._root_widget, selected_child=scrollwidget)

        # Keep our lock images up to date/etc.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()
Example #27
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 show_tab: str = None,
                 on_close_call: Callable[[], Any] = None,
                 back_location: str = None,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from bastd.ui import tabs
        from ba import SpecialChar

        app = ba.app
        uiscale = app.uiscale

        ba.set_analytics_screen('Store Window')

        scale_origin: Optional[Tuple[float, float]]

        # If they provided an origin-widget, scale up from that.
        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.button_infos: Optional[Dict[str, Dict[str, Any]]] = None
        self.update_buttons_timer: Optional[ba.Timer] = None
        self._status_textwidget_update_timer = None

        self._back_location = back_location
        self._on_close_call = on_close_call
        self._show_tab = show_tab
        self._modal = modal
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        self._x_inset = x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        645 if uiscale is ba.UIScale.MEDIUM else 800)
        self._current_tab: Optional[str] = None
        extra_top = 30 if uiscale is ba.UIScale.SMALL else 0

        self._request: Any = None
        self._r = 'store'
        self._last_buy_time: Optional[float] = None

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + extra_top),
            transition=transition,
            toolbar_visibility='menu_full',
            scale=(1.3 if uiscale is ba.UIScale.SMALL else
                   0.9 if uiscale is ba.UIScale.MEDIUM else 0.8),
            scale_origin_stack_offset=scale_origin,
            stack_offset=((0, -5) if uiscale is ba.UIScale.SMALL else (
                0, 0) if uiscale is ba.UIScale.MEDIUM else (0, 0))))

        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(70 + x_inset, self._height - 74),
            size=(140, 60),
            scale=1.1,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if self._modal else 'backText'),
            button_type=None if self._modal else 'back',
            on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        self._get_tickets_button = ba.buttonwidget(
            parent=self._root_widget,
            size=(210, 65),
            on_activate_call=self._on_get_more_tickets_press,
            autoselect=True,
            scale=0.9,
            text_scale=1.4,
            left_widget=self._back_button,
            color=(0.7, 0.5, 0.85),
            textcolor=(0.2, 1.0, 0.2),
            label=ba.Lstr(resource='getTicketsWindow.titleText'))

        # Move this dynamically to keep it out of the way of the party icon.
        self._update_get_tickets_button_pos()
        self._get_ticket_pos_update_timer = ba.Timer(
            1.0,
            ba.WeakCall(self._update_get_tickets_button_pos),
            repeat=True,
            timetype=ba.TimeType.REAL)
        ba.widget(edit=self._back_button,
                  right_widget=self._get_tickets_button)
        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()

        app = ba.app
        if app.platform in ['mac', 'ios'] and app.subplatform == 'appstore':
            ba.buttonwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 - 70, 16),
                size=(230, 50),
                scale=0.65,
                on_activate_call=ba.WeakCall(self._restore_purchases),
                color=(0.35, 0.3, 0.4),
                selectable=False,
                textcolor=(0.55, 0.5, 0.6),
                label=ba.Lstr(
                    resource='getTicketsWindow.restorePurchasesText'))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 44),
                      size=(0, 0),
                      color=app.title_color,
                      scale=1.5,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource='storeText'),
                      maxwidth=420)

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

        scroll_buffer_h = 130 + 2 * x_inset
        tab_buffer_h = 250 + 2 * x_inset

        tabs_def = [
            ('extras', ba.Lstr(resource=self._r + '.extrasText')),
            ('maps', ba.Lstr(resource=self._r + '.mapsText')),
            ('minigames', ba.Lstr(resource=self._r + '.miniGamesText')),
            ('characters', ba.Lstr(resource=self._r + '.charactersText')),
            ('icons', ba.Lstr(resource=self._r + '.iconsText')),
        ]

        tab_results = tabs.create_tab_buttons(self._root_widget,
                                              tabs_def,
                                              pos=(tab_buffer_h * 0.5,
                                                   self._height - 130),
                                              size=(self._width - tab_buffer_h,
                                                    50),
                                              on_select_call=self._set_tab,
                                              return_extra_info=True)

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

        # Create our purchasable-items tags and have them update over time.
        for i, tab in enumerate(tabs_def):
            pos = tab_results['positions'][i]
            size = tab_results['sizes'][i]
            button = tab_results['buttons_indexed'][i]
            rad = 10
            center = (pos[0] + 0.1 * size[0], pos[1] + 0.9 * size[1])
            img = ba.imagewidget(parent=self._root_widget,
                                 position=(center[0] - rad * 1.04,
                                           center[1] - rad * 1.15),
                                 size=(rad * 2.2, rad * 2.2),
                                 texture=ba.gettexture('circleShadow'),
                                 color=(1, 0, 0))
            txt = ba.textwidget(parent=self._root_widget,
                                position=center,
                                size=(0, 0),
                                h_align='center',
                                v_align='center',
                                maxwidth=1.4 * rad,
                                scale=0.6,
                                shadow=1.0,
                                flatness=1.0)
            rad = 20
            sale_img = ba.imagewidget(parent=self._root_widget,
                                      position=(center[0] - rad,
                                                center[1] - rad),
                                      size=(rad * 2, rad * 2),
                                      draw_controller=button,
                                      texture=ba.gettexture('circleZigZag'),
                                      color=(0.5, 0, 1.0))
            sale_title_text = ba.textwidget(parent=self._root_widget,
                                            position=(center[0],
                                                      center[1] + 0.24 * rad),
                                            size=(0, 0),
                                            h_align='center',
                                            v_align='center',
                                            draw_controller=button,
                                            maxwidth=1.4 * rad,
                                            scale=0.6,
                                            shadow=0.0,
                                            flatness=1.0,
                                            color=(0, 1, 0))
            sale_time_text = ba.textwidget(parent=self._root_widget,
                                           position=(center[0],
                                                     center[1] - 0.29 * rad),
                                           size=(0, 0),
                                           h_align='center',
                                           v_align='center',
                                           draw_controller=button,
                                           maxwidth=1.4 * rad,
                                           scale=0.4,
                                           shadow=0.0,
                                           flatness=1.0,
                                           color=(0, 1, 0))
            self._purchasable_count_widgets[tab[0]] = {
                'img': img,
                'text': txt,
                'sale_img': sale_img,
                'sale_title_text': sale_title_text,
                'sale_time_text': sale_time_text
            }
        self._tab_update_timer = ba.Timer(1.0,
                                          ba.WeakCall(self._update_tabs),
                                          timetype=ba.TimeType.REAL,
                                          repeat=True)
        self._update_tabs()

        self._tab_buttons = tab_results['buttons']

        if self._get_tickets_button is not None:
            last_tab_button = self._tab_buttons[tabs_def[-1][0]]
            ba.widget(edit=self._get_tickets_button,
                      down_widget=last_tab_button)
            ba.widget(edit=last_tab_button,
                      up_widget=self._get_tickets_button,
                      right_widget=self._get_tickets_button)

        self._scroll_width = self._width - scroll_buffer_h
        self._scroll_height = self._height - 180

        self._scrollwidget: Optional[ba.Widget] = None
        self._status_textwidget: Optional[ba.Widget] = None
        self._restore_state()
Example #28
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))
Example #29
0
                def instantiate(self, scrollwidget: ba.Widget,
                                tab_button: ba.Widget) -> None:
                    """Create the store."""
                    # pylint: disable=too-many-locals
                    # pylint: disable=too-many-branches
                    # pylint: disable=too-many-nested-blocks
                    from bastd.ui.store import item as storeitemui
                    title_spacing = 40
                    button_border = 20
                    button_spacing = 4
                    boffs_h = 40
                    self._height = 80.0

                    # Calc total height.
                    for i, section in enumerate(self._sections):
                        if section['title'] != '':
                            assert self._height is not None
                            self._height += title_spacing
                        b_width, b_height = section['button_size']
                        b_column_count = int(
                            math.floor((self._width - boffs_h - 20) /
                                       (b_width + button_spacing)))
                        b_row_count = int(
                            math.ceil(
                                float(len(section['items'])) / b_column_count))
                        b_height_total = (
                            2 * button_border + b_row_count * b_height +
                            (b_row_count - 1) * section['v_spacing'])
                        self._height += b_height_total

                    assert self._height is not None
                    cnt2 = ba.containerwidget(parent=scrollwidget,
                                              scale=1.0,
                                              size=(self._width, self._height),
                                              background=False)
                    ba.containerwidget(edit=cnt2,
                                       claims_left_right=True,
                                       claims_tab=True,
                                       selection_loop_to_parent=True)
                    v = self._height - 20

                    if self._tab == 'characters':
                        txt = ba.Lstr(
                            resource='store.howToSwitchCharactersText',
                            subs=[
                                ('${SETTINGS}',
                                 ba.Lstr(
                                     resource='accountSettingsWindow.titleText'
                                 )),
                                ('${PLAYER_PROFILES}',
                                 ba.Lstr(
                                     resource='playerProfilesWindow.titleText')
                                 )
                            ])
                        ba.textwidget(parent=cnt2,
                                      text=txt,
                                      size=(0, 0),
                                      position=(self._width * 0.5,
                                                self._height - 28),
                                      h_align='center',
                                      v_align='center',
                                      color=(0.7, 1, 0.7, 0.4),
                                      scale=0.7,
                                      shadow=0,
                                      flatness=1.0,
                                      maxwidth=700,
                                      transition_delay=0.4)
                    elif self._tab == 'icons':
                        txt = ba.Lstr(
                            resource='store.howToUseIconsText',
                            subs=[
                                ('${SETTINGS}',
                                 ba.Lstr(resource='mainMenu.settingsText')),
                                ('${PLAYER_PROFILES}',
                                 ba.Lstr(
                                     resource='playerProfilesWindow.titleText')
                                 )
                            ])
                        ba.textwidget(parent=cnt2,
                                      text=txt,
                                      size=(0, 0),
                                      position=(self._width * 0.5,
                                                self._height - 28),
                                      h_align='center',
                                      v_align='center',
                                      color=(0.7, 1, 0.7, 0.4),
                                      scale=0.7,
                                      shadow=0,
                                      flatness=1.0,
                                      maxwidth=700,
                                      transition_delay=0.4)
                    elif self._tab == 'maps':
                        assert self._width is not None
                        assert self._height is not None
                        txt = ba.Lstr(resource='store.howToUseMapsText')
                        ba.textwidget(parent=cnt2,
                                      text=txt,
                                      size=(0, 0),
                                      position=(self._width * 0.5,
                                                self._height - 28),
                                      h_align='center',
                                      v_align='center',
                                      color=(0.7, 1, 0.7, 0.4),
                                      scale=0.7,
                                      shadow=0,
                                      flatness=1.0,
                                      maxwidth=700,
                                      transition_delay=0.4)

                    prev_row_buttons: Optional[List] = None
                    this_row_buttons = []

                    delay = 0.3
                    for section in self._sections:
                        if section['title'] != '':
                            ba.textwidget(
                                parent=cnt2,
                                position=(60, v - title_spacing * 0.8),
                                size=(0, 0),
                                scale=1.0,
                                transition_delay=delay,
                                color=(0.7, 0.9, 0.7, 1),
                                h_align='left',
                                v_align='center',
                                text=ba.Lstr(resource=section['title']),
                                maxwidth=self._width * 0.7)
                            v -= title_spacing
                        delay = max(0.100, delay - 0.100)
                        v -= button_border
                        b_width, b_height = section['button_size']
                        b_count = len(section['items'])
                        b_column_count = int(
                            math.floor((self._width - boffs_h - 20) /
                                       (b_width + button_spacing)))
                        col = 0
                        item: Dict[str, Any]
                        assert self._store_window.button_infos is not None
                        for i, item_name in enumerate(section['items']):
                            item = self._store_window.button_infos[
                                item_name] = {}
                            item['call'] = ba.WeakCall(self._store_window.buy,
                                                       item_name)
                            if 'x_offs' in section:
                                boffs_h2 = section['x_offs']
                            else:
                                boffs_h2 = 0

                            if 'y_offs' in section:
                                boffs_v2 = section['y_offs']
                            else:
                                boffs_v2 = 0
                            b_pos = (boffs_h + boffs_h2 +
                                     (b_width + button_spacing) * col,
                                     v - b_height + boffs_v2)
                            storeitemui.instantiate_store_item_display(
                                item_name,
                                item,
                                parent_widget=cnt2,
                                b_pos=b_pos,
                                boffs_h=boffs_h,
                                b_width=b_width,
                                b_height=b_height,
                                boffs_h2=boffs_h2,
                                boffs_v2=boffs_v2,
                                delay=delay)
                            btn = item['button']
                            delay = max(0.1, delay - 0.1)
                            this_row_buttons.append(btn)

                            # Wire this button to the equivalent in the
                            # previous row.
                            if prev_row_buttons is not None:
                                # pylint: disable=unsubscriptable-object
                                if len(prev_row_buttons) > col:
                                    ba.widget(edit=btn,
                                              up_widget=prev_row_buttons[col])
                                    ba.widget(edit=prev_row_buttons[col],
                                              down_widget=btn)

                                    # If we're the last button in our row,
                                    # wire any in the previous row past
                                    # our position to go to us if down is
                                    # pressed.
                                    if (col + 1 == b_column_count
                                            or i == b_count - 1):
                                        for b_prev in prev_row_buttons[col +
                                                                       1:]:
                                            ba.widget(edit=b_prev,
                                                      down_widget=btn)
                                else:
                                    ba.widget(edit=btn,
                                              up_widget=prev_row_buttons[-1])
                            else:
                                ba.widget(edit=btn, up_widget=tab_button)

                            col += 1
                            if col == b_column_count or i == b_count - 1:
                                prev_row_buttons = this_row_buttons
                                this_row_buttons = []
                                col = 0
                                v -= b_height
                                if i < b_count - 1:
                                    v -= section['v_spacing']

                        v -= button_border

                    # Set a timer to update these buttons periodically as long
                    # as we're alive (so if we buy one it will grey out, etc).
                    self._store_window.update_buttons_timer = ba.Timer(
                        0.5,
                        ba.WeakCall(self._store_window.update_buttons),
                        repeat=True,
                        timetype=ba.TimeType.REAL)

                    # Also update them immediately.
                    self._store_window.update_buttons()
Example #30
0
    def __init__(self,
                 tournament_id: str,
                 tournament_activity: ba.GameActivity = None,
                 position: Tuple[float, float] = (0.0, 0.0),
                 scale: float = None,
                 offset: Tuple[float, float] = (0.0, 0.0),
                 tint_color: Sequence[float] = (1.0, 1.0, 1.0),
                 tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
                 selected_character: str = None,
                 on_close_call: Callable[[], Any] = None):

        del tournament_activity  # unused arg
        del tint_color  # unused arg
        del tint2_color  # unused arg
        del selected_character  # unused arg
        self._tournament_id = tournament_id
        self._subcontainer: Optional[ba.Widget] = None
        self._on_close_call = on_close_call
        uiscale = ba.app.ui.uiscale
        if scale is None:
            scale = (2.3 if uiscale is ba.UIScale.SMALL else
                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
        self._transitioning_out = False

        self._width = 400
        self._height = (300 if uiscale is ba.UIScale.SMALL else
                        370 if uiscale is ba.UIScale.MEDIUM else 450)

        bg_color = (0.5, 0.4, 0.6)

        # creates our _root_widget
        super().__init__(position=position,
                         size=(self._width, self._height),
                         scale=scale,
                         bg_color=bg_color,
                         offset=offset)

        # app = ba.app

        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='tournamentStandingsText'),
            maxwidth=200,
            color=(1, 1, 1, 0.4))

        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
                                             size=(self._width - 60,
                                                   self._height - 70),
                                             position=(30, 30),
                                             highlight=False,
                                             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')

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

        _ba.tournament_query(args={
            'tournamentIDs': [tournament_id],
            'numScores': 50,
            'source': 'scores window'
        },
                             callback=ba.WeakCall(
                                 self._on_tournament_query_response))