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()