bastd.ui.coop.gamebutton

Defines button for co-op games.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Defines button for co-op games."""
  4
  5from __future__ import annotations
  6
  7import random
  8from typing import TYPE_CHECKING
  9
 10import _ba
 11import ba
 12
 13if TYPE_CHECKING:
 14    from bastd.ui.coop.browser import CoopBrowserWindow
 15
 16
 17class GameButton:
 18    """Button for entering co-op games."""
 19
 20    def __init__(self, window: CoopBrowserWindow, parent: ba.Widget, game: str,
 21                 x: float, y: float, select: bool, row: str):
 22        # pylint: disable=too-many-statements
 23        # pylint: disable=too-many-locals
 24        from ba.internal import getcampaign
 25        self._game = game
 26        sclx = 195.0
 27        scly = 195.0
 28
 29        campaignname, levelname = game.split(':')
 30
 31        # Hack: The Last Stand doesn't actually exist in the easy
 32        # tourney. We just want it for display purposes. Map it to
 33        # the hard-mode version.
 34        if game == 'Easy:The Last Stand':
 35            campaignname = 'Default'
 36
 37        rating: float | None
 38        campaign = getcampaign(campaignname)
 39        rating = campaign.getlevel(levelname).rating
 40
 41        if game == 'Easy:The Last Stand':
 42            rating = None
 43
 44        if rating is None or rating == 0.0:
 45            stars = 0
 46        elif rating >= 9.5:
 47            stars = 3
 48        elif rating >= 7.5:
 49            stars = 2
 50        else:
 51            stars = 1
 52
 53        self._button = btn = ba.buttonwidget(
 54            parent=parent,
 55            position=(x + 23, y + 4),
 56            size=(sclx, scly),
 57            label='',
 58            on_activate_call=ba.Call(window.run_game, game),
 59            button_type='square',
 60            autoselect=True,
 61            on_select_call=ba.Call(window.sel_change, row, game))
 62        ba.widget(edit=btn,
 63                  show_buffer_bottom=50,
 64                  show_buffer_top=50,
 65                  show_buffer_left=400,
 66                  show_buffer_right=200)
 67        if select:
 68            ba.containerwidget(edit=parent,
 69                               selected_child=btn,
 70                               visible_child=btn)
 71        image_width = sclx * 0.85 * 0.75
 72        self._preview_widget = ba.imagewidget(
 73            parent=parent,
 74            draw_controller=btn,
 75            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104),
 76            size=(image_width, image_width * 0.5),
 77            model_transparent=window.lsbt,
 78            model_opaque=window.lsbo,
 79            texture=campaign.getlevel(levelname).get_preview_texture(),
 80            mask_texture=ba.gettexture('mapPreviewMask'))
 81
 82        translated = campaign.getlevel(levelname).displayname
 83        self._achievements = ba.app.ach.achievements_for_coop_level(game)
 84
 85        self._name_widget = ba.textwidget(parent=parent,
 86                                          draw_controller=btn,
 87                                          position=(x + 20 + sclx * 0.5,
 88                                                    y + scly - 27),
 89                                          size=(0, 0),
 90                                          h_align='center',
 91                                          text=translated,
 92                                          v_align='center',
 93                                          maxwidth=sclx * 0.76,
 94                                          scale=0.85)
 95        xscl = x + (67 if self._achievements else 50)
 96        yscl = y + scly - (137 if self._achievements else 157)
 97
 98        starscale = 35.0 if self._achievements else 45.0
 99
100        self._star_widgets: list[ba.Widget] = []
101        for _i in range(stars):
102            imw = ba.imagewidget(parent=parent,
103                                 draw_controller=btn,
104                                 position=(xscl, yscl),
105                                 size=(starscale, starscale),
106                                 texture=window.star_tex)
107            self._star_widgets.append(imw)
108            xscl += starscale
109        for _i in range(3 - stars):
110            ba.imagewidget(parent=parent,
111                           draw_controller=btn,
112                           position=(xscl, yscl),
113                           size=(starscale, starscale),
114                           color=(0, 0, 0),
115                           texture=window.star_tex,
116                           opacity=0.3)
117            xscl += starscale
118
119        xach = x + 69
120        yach = y + scly - 168
121        a_scale = 30.0
122        self._achievement_widgets: list[tuple[ba.Widget, ba.Widget]] = []
123        for ach in self._achievements:
124            a_complete = ach.complete
125            imw = ba.imagewidget(
126                parent=parent,
127                draw_controller=btn,
128                position=(xach, yach),
129                size=(a_scale, a_scale),
130                color=tuple(ach.get_icon_color(a_complete)[:3])
131                if a_complete else (1.2, 1.2, 1.2),
132                texture=ach.get_icon_texture(a_complete))
133            imw2 = ba.imagewidget(parent=parent,
134                                  draw_controller=btn,
135                                  position=(xach, yach),
136                                  size=(a_scale, a_scale),
137                                  color=(2, 1.4, 0.4),
138                                  texture=window.a_outline_tex,
139                                  model_transparent=window.a_outline_model)
140            self._achievement_widgets.append((imw, imw2))
141            # if a_complete:
142            xach += a_scale * 1.2
143
144        # if not unlocked:
145        self._lock_widget = ba.imagewidget(parent=parent,
146                                           draw_controller=btn,
147                                           position=(x - 8 + sclx * 0.5,
148                                                     y + scly * 0.5 - 20),
149                                           size=(60, 60),
150                                           opacity=0.0,
151                                           texture=ba.gettexture('lock'))
152
153        # give a quasi-random update increment to spread the load..
154        self._update_timer = ba.Timer(0.001 * (900 + random.randrange(200)),
155                                      ba.WeakCall(self._update),
156                                      repeat=True,
157                                      timetype=ba.TimeType.REAL)
158        self._update()
159
160    def get_button(self) -> ba.Widget:
161        """Return the underlying button ba.Widget."""
162        return self._button
163
164    def _update(self) -> None:
165        # pylint: disable=too-many-boolean-expressions
166        from ba.internal import getcampaign
167
168        # In case we stick around after our UI...
169        if not self._button:
170            return
171
172        game = self._game
173        campaignname, levelname = game.split(':')
174
175        # Hack - The Last Stand doesn't actually exist in the
176        # easy tourney; we just want it for display purposes. Map it to
177        # the hard-mode version.
178        if game == 'Easy:The Last Stand':
179            campaignname = 'Default'
180
181        campaign = getcampaign(campaignname)
182
183        # If this campaign is sequential, make sure we've unlocked
184        # everything up to here.
185        unlocked = True
186        if campaign.sequential:
187            for level in campaign.levels:
188                if level.name == levelname:
189                    break
190                if not level.complete:
191                    unlocked = False
192                    break
193
194        # We never actually allow playing last-stand on easy mode.
195        if game == 'Easy:The Last Stand':
196            unlocked = False
197
198        # Hard-code games we haven't unlocked.
199        if ((game in ('Challenges:Infinite Runaround',
200                      'Challenges:Infinite Onslaught')
201             and not ba.app.accounts_v1.have_pro())
202                or (game in ('Challenges:Meteor Shower', )
203                    and not _ba.get_purchased('games.meteor_shower'))
204                or (game in ('Challenges:Target Practice',
205                             'Challenges:Target Practice B')
206                    and not _ba.get_purchased('games.target_practice'))
207                or (game in ('Challenges:Ninja Fight', )
208                    and not _ba.get_purchased('games.ninja_fight'))
209                or (game in ('Challenges:Pro Ninja Fight', )
210                    and not _ba.get_purchased('games.ninja_fight'))
211                or (game in ('Challenges:Easter Egg Hunt',
212                             'Challenges:Pro Easter Egg Hunt')
213                    and not _ba.get_purchased('games.easter_egg_hunt'))):
214            unlocked = False
215
216        # Let's tint levels a slightly different color when easy mode
217        # is selected.
218        unlocked_color = (0.85, 0.95,
219                          0.5) if game.startswith('Easy:') else (0.5, 0.7, 0.2)
220
221        ba.buttonwidget(edit=self._button,
222                        color=unlocked_color if unlocked else (0.5, 0.5, 0.5))
223
224        ba.imagewidget(edit=self._lock_widget,
225                       opacity=0.0 if unlocked else 1.0)
226        ba.imagewidget(edit=self._preview_widget,
227                       opacity=1.0 if unlocked else 0.3)
228        ba.textwidget(edit=self._name_widget,
229                      color=(0.8, 1.0, 0.8, 1.0) if unlocked else
230                      (0.7, 0.7, 0.7, 0.7))
231        for widget in self._star_widgets:
232            ba.imagewidget(edit=widget,
233                           opacity=1.0 if unlocked else 0.3,
234                           color=(2.2, 1.2, 0.3) if unlocked else (1, 1, 1))
235        for i, ach in enumerate(self._achievements):
236            a_complete = ach.complete
237            ba.imagewidget(edit=self._achievement_widgets[i][0],
238                           opacity=1.0 if (a_complete and unlocked) else 0.3)
239            ba.imagewidget(edit=self._achievement_widgets[i][1],
240                           opacity=(1.0 if (a_complete and unlocked) else
241                                    0.2 if a_complete else 0.0))
class GameButton:
 18class GameButton:
 19    """Button for entering co-op games."""
 20
 21    def __init__(self, window: CoopBrowserWindow, parent: ba.Widget, game: str,
 22                 x: float, y: float, select: bool, row: str):
 23        # pylint: disable=too-many-statements
 24        # pylint: disable=too-many-locals
 25        from ba.internal import getcampaign
 26        self._game = game
 27        sclx = 195.0
 28        scly = 195.0
 29
 30        campaignname, levelname = game.split(':')
 31
 32        # Hack: The Last Stand doesn't actually exist in the easy
 33        # tourney. We just want it for display purposes. Map it to
 34        # the hard-mode version.
 35        if game == 'Easy:The Last Stand':
 36            campaignname = 'Default'
 37
 38        rating: float | None
 39        campaign = getcampaign(campaignname)
 40        rating = campaign.getlevel(levelname).rating
 41
 42        if game == 'Easy:The Last Stand':
 43            rating = None
 44
 45        if rating is None or rating == 0.0:
 46            stars = 0
 47        elif rating >= 9.5:
 48            stars = 3
 49        elif rating >= 7.5:
 50            stars = 2
 51        else:
 52            stars = 1
 53
 54        self._button = btn = ba.buttonwidget(
 55            parent=parent,
 56            position=(x + 23, y + 4),
 57            size=(sclx, scly),
 58            label='',
 59            on_activate_call=ba.Call(window.run_game, game),
 60            button_type='square',
 61            autoselect=True,
 62            on_select_call=ba.Call(window.sel_change, row, game))
 63        ba.widget(edit=btn,
 64                  show_buffer_bottom=50,
 65                  show_buffer_top=50,
 66                  show_buffer_left=400,
 67                  show_buffer_right=200)
 68        if select:
 69            ba.containerwidget(edit=parent,
 70                               selected_child=btn,
 71                               visible_child=btn)
 72        image_width = sclx * 0.85 * 0.75
 73        self._preview_widget = ba.imagewidget(
 74            parent=parent,
 75            draw_controller=btn,
 76            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104),
 77            size=(image_width, image_width * 0.5),
 78            model_transparent=window.lsbt,
 79            model_opaque=window.lsbo,
 80            texture=campaign.getlevel(levelname).get_preview_texture(),
 81            mask_texture=ba.gettexture('mapPreviewMask'))
 82
 83        translated = campaign.getlevel(levelname).displayname
 84        self._achievements = ba.app.ach.achievements_for_coop_level(game)
 85
 86        self._name_widget = ba.textwidget(parent=parent,
 87                                          draw_controller=btn,
 88                                          position=(x + 20 + sclx * 0.5,
 89                                                    y + scly - 27),
 90                                          size=(0, 0),
 91                                          h_align='center',
 92                                          text=translated,
 93                                          v_align='center',
 94                                          maxwidth=sclx * 0.76,
 95                                          scale=0.85)
 96        xscl = x + (67 if self._achievements else 50)
 97        yscl = y + scly - (137 if self._achievements else 157)
 98
 99        starscale = 35.0 if self._achievements else 45.0
100
101        self._star_widgets: list[ba.Widget] = []
102        for _i in range(stars):
103            imw = ba.imagewidget(parent=parent,
104                                 draw_controller=btn,
105                                 position=(xscl, yscl),
106                                 size=(starscale, starscale),
107                                 texture=window.star_tex)
108            self._star_widgets.append(imw)
109            xscl += starscale
110        for _i in range(3 - stars):
111            ba.imagewidget(parent=parent,
112                           draw_controller=btn,
113                           position=(xscl, yscl),
114                           size=(starscale, starscale),
115                           color=(0, 0, 0),
116                           texture=window.star_tex,
117                           opacity=0.3)
118            xscl += starscale
119
120        xach = x + 69
121        yach = y + scly - 168
122        a_scale = 30.0
123        self._achievement_widgets: list[tuple[ba.Widget, ba.Widget]] = []
124        for ach in self._achievements:
125            a_complete = ach.complete
126            imw = ba.imagewidget(
127                parent=parent,
128                draw_controller=btn,
129                position=(xach, yach),
130                size=(a_scale, a_scale),
131                color=tuple(ach.get_icon_color(a_complete)[:3])
132                if a_complete else (1.2, 1.2, 1.2),
133                texture=ach.get_icon_texture(a_complete))
134            imw2 = ba.imagewidget(parent=parent,
135                                  draw_controller=btn,
136                                  position=(xach, yach),
137                                  size=(a_scale, a_scale),
138                                  color=(2, 1.4, 0.4),
139                                  texture=window.a_outline_tex,
140                                  model_transparent=window.a_outline_model)
141            self._achievement_widgets.append((imw, imw2))
142            # if a_complete:
143            xach += a_scale * 1.2
144
145        # if not unlocked:
146        self._lock_widget = ba.imagewidget(parent=parent,
147                                           draw_controller=btn,
148                                           position=(x - 8 + sclx * 0.5,
149                                                     y + scly * 0.5 - 20),
150                                           size=(60, 60),
151                                           opacity=0.0,
152                                           texture=ba.gettexture('lock'))
153
154        # give a quasi-random update increment to spread the load..
155        self._update_timer = ba.Timer(0.001 * (900 + random.randrange(200)),
156                                      ba.WeakCall(self._update),
157                                      repeat=True,
158                                      timetype=ba.TimeType.REAL)
159        self._update()
160
161    def get_button(self) -> ba.Widget:
162        """Return the underlying button ba.Widget."""
163        return self._button
164
165    def _update(self) -> None:
166        # pylint: disable=too-many-boolean-expressions
167        from ba.internal import getcampaign
168
169        # In case we stick around after our UI...
170        if not self._button:
171            return
172
173        game = self._game
174        campaignname, levelname = game.split(':')
175
176        # Hack - The Last Stand doesn't actually exist in the
177        # easy tourney; we just want it for display purposes. Map it to
178        # the hard-mode version.
179        if game == 'Easy:The Last Stand':
180            campaignname = 'Default'
181
182        campaign = getcampaign(campaignname)
183
184        # If this campaign is sequential, make sure we've unlocked
185        # everything up to here.
186        unlocked = True
187        if campaign.sequential:
188            for level in campaign.levels:
189                if level.name == levelname:
190                    break
191                if not level.complete:
192                    unlocked = False
193                    break
194
195        # We never actually allow playing last-stand on easy mode.
196        if game == 'Easy:The Last Stand':
197            unlocked = False
198
199        # Hard-code games we haven't unlocked.
200        if ((game in ('Challenges:Infinite Runaround',
201                      'Challenges:Infinite Onslaught')
202             and not ba.app.accounts_v1.have_pro())
203                or (game in ('Challenges:Meteor Shower', )
204                    and not _ba.get_purchased('games.meteor_shower'))
205                or (game in ('Challenges:Target Practice',
206                             'Challenges:Target Practice B')
207                    and not _ba.get_purchased('games.target_practice'))
208                or (game in ('Challenges:Ninja Fight', )
209                    and not _ba.get_purchased('games.ninja_fight'))
210                or (game in ('Challenges:Pro Ninja Fight', )
211                    and not _ba.get_purchased('games.ninja_fight'))
212                or (game in ('Challenges:Easter Egg Hunt',
213                             'Challenges:Pro Easter Egg Hunt')
214                    and not _ba.get_purchased('games.easter_egg_hunt'))):
215            unlocked = False
216
217        # Let's tint levels a slightly different color when easy mode
218        # is selected.
219        unlocked_color = (0.85, 0.95,
220                          0.5) if game.startswith('Easy:') else (0.5, 0.7, 0.2)
221
222        ba.buttonwidget(edit=self._button,
223                        color=unlocked_color if unlocked else (0.5, 0.5, 0.5))
224
225        ba.imagewidget(edit=self._lock_widget,
226                       opacity=0.0 if unlocked else 1.0)
227        ba.imagewidget(edit=self._preview_widget,
228                       opacity=1.0 if unlocked else 0.3)
229        ba.textwidget(edit=self._name_widget,
230                      color=(0.8, 1.0, 0.8, 1.0) if unlocked else
231                      (0.7, 0.7, 0.7, 0.7))
232        for widget in self._star_widgets:
233            ba.imagewidget(edit=widget,
234                           opacity=1.0 if unlocked else 0.3,
235                           color=(2.2, 1.2, 0.3) if unlocked else (1, 1, 1))
236        for i, ach in enumerate(self._achievements):
237            a_complete = ach.complete
238            ba.imagewidget(edit=self._achievement_widgets[i][0],
239                           opacity=1.0 if (a_complete and unlocked) else 0.3)
240            ba.imagewidget(edit=self._achievement_widgets[i][1],
241                           opacity=(1.0 if (a_complete and unlocked) else
242                                    0.2 if a_complete else 0.0))

Button for entering co-op games.

GameButton( window: bastd.ui.coop.browser.CoopBrowserWindow, parent: _ba.Widget, game: str, x: float, y: float, select: bool, row: str)
 21    def __init__(self, window: CoopBrowserWindow, parent: ba.Widget, game: str,
 22                 x: float, y: float, select: bool, row: str):
 23        # pylint: disable=too-many-statements
 24        # pylint: disable=too-many-locals
 25        from ba.internal import getcampaign
 26        self._game = game
 27        sclx = 195.0
 28        scly = 195.0
 29
 30        campaignname, levelname = game.split(':')
 31
 32        # Hack: The Last Stand doesn't actually exist in the easy
 33        # tourney. We just want it for display purposes. Map it to
 34        # the hard-mode version.
 35        if game == 'Easy:The Last Stand':
 36            campaignname = 'Default'
 37
 38        rating: float | None
 39        campaign = getcampaign(campaignname)
 40        rating = campaign.getlevel(levelname).rating
 41
 42        if game == 'Easy:The Last Stand':
 43            rating = None
 44
 45        if rating is None or rating == 0.0:
 46            stars = 0
 47        elif rating >= 9.5:
 48            stars = 3
 49        elif rating >= 7.5:
 50            stars = 2
 51        else:
 52            stars = 1
 53
 54        self._button = btn = ba.buttonwidget(
 55            parent=parent,
 56            position=(x + 23, y + 4),
 57            size=(sclx, scly),
 58            label='',
 59            on_activate_call=ba.Call(window.run_game, game),
 60            button_type='square',
 61            autoselect=True,
 62            on_select_call=ba.Call(window.sel_change, row, game))
 63        ba.widget(edit=btn,
 64                  show_buffer_bottom=50,
 65                  show_buffer_top=50,
 66                  show_buffer_left=400,
 67                  show_buffer_right=200)
 68        if select:
 69            ba.containerwidget(edit=parent,
 70                               selected_child=btn,
 71                               visible_child=btn)
 72        image_width = sclx * 0.85 * 0.75
 73        self._preview_widget = ba.imagewidget(
 74            parent=parent,
 75            draw_controller=btn,
 76            position=(x + 21 + sclx * 0.5 - image_width * 0.5, y + scly - 104),
 77            size=(image_width, image_width * 0.5),
 78            model_transparent=window.lsbt,
 79            model_opaque=window.lsbo,
 80            texture=campaign.getlevel(levelname).get_preview_texture(),
 81            mask_texture=ba.gettexture('mapPreviewMask'))
 82
 83        translated = campaign.getlevel(levelname).displayname
 84        self._achievements = ba.app.ach.achievements_for_coop_level(game)
 85
 86        self._name_widget = ba.textwidget(parent=parent,
 87                                          draw_controller=btn,
 88                                          position=(x + 20 + sclx * 0.5,
 89                                                    y + scly - 27),
 90                                          size=(0, 0),
 91                                          h_align='center',
 92                                          text=translated,
 93                                          v_align='center',
 94                                          maxwidth=sclx * 0.76,
 95                                          scale=0.85)
 96        xscl = x + (67 if self._achievements else 50)
 97        yscl = y + scly - (137 if self._achievements else 157)
 98
 99        starscale = 35.0 if self._achievements else 45.0
100
101        self._star_widgets: list[ba.Widget] = []
102        for _i in range(stars):
103            imw = ba.imagewidget(parent=parent,
104                                 draw_controller=btn,
105                                 position=(xscl, yscl),
106                                 size=(starscale, starscale),
107                                 texture=window.star_tex)
108            self._star_widgets.append(imw)
109            xscl += starscale
110        for _i in range(3 - stars):
111            ba.imagewidget(parent=parent,
112                           draw_controller=btn,
113                           position=(xscl, yscl),
114                           size=(starscale, starscale),
115                           color=(0, 0, 0),
116                           texture=window.star_tex,
117                           opacity=0.3)
118            xscl += starscale
119
120        xach = x + 69
121        yach = y + scly - 168
122        a_scale = 30.0
123        self._achievement_widgets: list[tuple[ba.Widget, ba.Widget]] = []
124        for ach in self._achievements:
125            a_complete = ach.complete
126            imw = ba.imagewidget(
127                parent=parent,
128                draw_controller=btn,
129                position=(xach, yach),
130                size=(a_scale, a_scale),
131                color=tuple(ach.get_icon_color(a_complete)[:3])
132                if a_complete else (1.2, 1.2, 1.2),
133                texture=ach.get_icon_texture(a_complete))
134            imw2 = ba.imagewidget(parent=parent,
135                                  draw_controller=btn,
136                                  position=(xach, yach),
137                                  size=(a_scale, a_scale),
138                                  color=(2, 1.4, 0.4),
139                                  texture=window.a_outline_tex,
140                                  model_transparent=window.a_outline_model)
141            self._achievement_widgets.append((imw, imw2))
142            # if a_complete:
143            xach += a_scale * 1.2
144
145        # if not unlocked:
146        self._lock_widget = ba.imagewidget(parent=parent,
147                                           draw_controller=btn,
148                                           position=(x - 8 + sclx * 0.5,
149                                                     y + scly * 0.5 - 20),
150                                           size=(60, 60),
151                                           opacity=0.0,
152                                           texture=ba.gettexture('lock'))
153
154        # give a quasi-random update increment to spread the load..
155        self._update_timer = ba.Timer(0.001 * (900 + random.randrange(200)),
156                                      ba.WeakCall(self._update),
157                                      repeat=True,
158                                      timetype=ba.TimeType.REAL)
159        self._update()
def get_button(self) -> _ba.Widget:
161    def get_button(self) -> ba.Widget:
162        """Return the underlying button ba.Widget."""
163        return self._button

Return the underlying button ba.Widget.