def __init__(self) -> None: """Instantiate a factory object.""" # pylint: disable=cyclic-import # FIXME: should probably put these somewhere common so we don't # have to import them from a module that imports us. from bastd.actor.spaz import (PickupMessage, PunchHitMessage, CurseExplodeMessage) shared = SharedObjects.get() self.impact_sounds_medium = (ba.getsound('impactMedium'), ba.getsound('impactMedium2')) self.impact_sounds_hard = (ba.getsound('impactHard'), ba.getsound('impactHard2'), ba.getsound('impactHard3')) self.impact_sounds_harder = (ba.getsound('bigImpact'), ba.getsound('bigImpact2')) self.single_player_death_sound = ba.getsound('playerDeath') self.punch_sound = ba.getsound('punch01') self.punch_sound_strong = (ba.getsound('punchStrong01'), ba.getsound('punchStrong02')) self.punch_sound_stronger = ba.getsound('superPunch') self.swish_sound = ba.getsound('punchSwish') self.block_sound = ba.getsound('block') self.shatter_sound = ba.getsound('shatter') self.splatter_sound = ba.getsound('splatter') self.spaz_material = ba.Material() self.roller_material = ba.Material() self.punch_material = ba.Material() self.pickup_material = ba.Material() self.curse_material = ba.Material() footing_material = shared.footing_material object_material = shared.object_material player_material = shared.player_material region_material = shared.region_material # Send footing messages to spazzes so they know when they're on # solid ground. # Eww; this probably should just be built into the spaz node. self.roller_material.add_actions( conditions=('they_have_material', footing_material), actions=(('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1))) self.spaz_material.add_actions( conditions=('they_have_material', footing_material), actions=(('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1))) # Punches. self.punch_material.add_actions( conditions=('they_are_different_node_than_us', ), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', PunchHitMessage()), )) # Pickups. self.pickup_material.add_actions( conditions=(('they_are_different_node_than_us', ), 'and', ('they_have_material', object_material)), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', PickupMessage()), )) # Curse. self.curse_material.add_actions( conditions=( ('they_are_different_node_than_us', ), 'and', ('they_have_material', player_material), ), actions=('message', 'our_node', 'at_connect', CurseExplodeMessage()), ) self.foot_impact_sounds = (ba.getsound('footImpact01'), ba.getsound('footImpact02'), ba.getsound('footImpact03')) self.foot_skid_sound = ba.getsound('skid01') self.foot_roll_sound = ba.getsound('scamper01') self.roller_material.add_actions( conditions=('they_have_material', footing_material), actions=( ('impact_sound', self.foot_impact_sounds, 1, 0.2), ('skid_sound', self.foot_skid_sound, 20, 0.3), ('roll_sound', self.foot_roll_sound, 20, 3.0), )) self.skid_sound = ba.getsound('gravelSkid') self.spaz_material.add_actions( conditions=('they_have_material', footing_material), actions=( ('impact_sound', self.foot_impact_sounds, 20, 6), ('skid_sound', self.skid_sound, 2.0, 1), ('roll_sound', self.skid_sound, 2.0, 1), )) self.shield_up_sound = ba.getsound('shieldUp') self.shield_down_sound = ba.getsound('shieldDown') self.shield_hit_sound = ba.getsound('shieldHit') # We don't want to collide with stuff we're initially overlapping # (unless its marked with a special region material). self.spaz_material.add_actions( conditions=( ( ('we_are_younger_than', 51), 'and', ('they_are_different_node_than_us', ), ), 'and', ('they_dont_have_material', region_material), ), actions=('modify_node_collision', 'collide', False), ) self.spaz_media: Dict[str, Any] = {} # Lets load some basic rules. # (allows them to be tweaked from the master server) self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0) self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400) self.punch_cooldown_gloves = (_ba.get_account_misc_read_val( 'rpcg', 300)) self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2) self.punch_power_scale_gloves = (_ba.get_account_misc_read_val( 'rppg', 1.4)) self.max_shield_spillover_damage = (_ba.get_account_misc_read_val( 'rsms', 500))
def _cancel(self) -> None: if self._cancel_delay > 0: ba.playsound(ba.getsound('error')) return self._transition_out('out_right')
def __init__(self, settings: dict): super().__init__(settings) shared = SharedObjects.get() self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') self._tick_sound = ba.getsound('tick') self._countdownsounds = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_pos: Optional[Sequence[float]] = None self._flag_state: Optional[FlagState] = None self._flag: Optional[Flag] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[ReferenceType[Team]] = None self._hold_time = int(settings['Hold Time']) self._time_limit = float(settings['Time Limit']) self._flag_region_material = ba.Material() self._flag_region_material.add_actions( conditions=('they_have_material', shared.player_material), actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', ba.Call(self._handle_player_flag_region_collide, True)), ('call', 'at_disconnect', ba.Call(self._handle_player_flag_region_collide, False)), )) # Base class overrides. self.default_music = ba.MusicType.SCARY
def _load_keyboard(self) -> None: # pylint: disable=too-many-locals self._keyboard = self._get_keyboard() # We want to get just chars without column data, etc. self._chars = [j for i in self._keyboard.chars for j in i] self._modes = ['normal'] + list(self._keyboard.pages) self._mode_index = 0 self._mode = self._modes[self._mode_index] v = self._height - 180.0 key_width = 46 * 10 / len(self._keyboard.chars[0]) key_height = 46 * 3 / len(self._keyboard.chars) key_textcolor = (1, 1, 1) row_starts = (69.0, 95.0, 151.0) key_color = self._key_color key_color_dark = self._key_color_dark self._click_sound = ba.getsound('click01') # kill prev char keys for key in self._char_keys: key.delete() self._char_keys = [] # dummy data just used for row/column lengths... we don't actually # set things until refresh chars: List[Tuple[str, ...]] = self._keyboard.chars for row_num, row in enumerate(chars): h = row_starts[row_num] # shift key before row 3 if row_num == 2 and self._shift_button is None: self._shift_button = ba.buttonwidget( parent=self._root_widget, position=(h - key_width * 2.0, v), size=(key_width * 1.7, key_height), autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.SHIFT), enable_sound=False, extra_touch_border_scale=0.3, button_type='square', ) for _ in row: btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(key_width, key_height), autoselect=True, enable_sound=False, textcolor=key_textcolor, color=key_color, label='', button_type='square', extra_touch_border_scale=0.1, ) self._char_keys.append(btn) h += key_width + 10 # Add delete key at end of third row. if row_num == 2: if self._backspace_button is not None: self._backspace_button.delete() self._backspace_button = ba.buttonwidget( parent=self._root_widget, position=(h + 4, v), size=(key_width * 1.8, key_height), autoselect=True, enable_sound=False, repeat=True, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.DELETE), button_type='square', on_activate_call=self._del) v -= (key_height + 9) # Do space bar and stuff. if row_num == 2: if self._num_mode_button is None: self._num_mode_button = ba.buttonwidget( parent=self._root_widget, position=(112, v - 8), size=(key_width * 2, key_height + 5), enable_sound=False, button_type='square', extra_touch_border_scale=0.3, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label='', ) if self._emoji_button is None: self._emoji_button = ba.buttonwidget( parent=self._root_widget, position=(56, v - 8), size=(key_width, key_height + 5), autoselect=True, enable_sound=False, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.LOGO_FLAT), extra_touch_border_scale=0.3, button_type='square', ) btn1 = self._num_mode_button if self._space_button is None: self._space_button = ba.buttonwidget( parent=self._root_widget, position=(210, v - 12), size=(key_width * 6.1, key_height + 15), extra_touch_border_scale=0.3, enable_sound=False, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=ba.Lstr(resource='spaceKeyText'), on_activate_call=ba.Call(self._type_char, ' ')) # Show change instructions only if we have more than one # keyboard option. if (ba.app.meta.metascan is not None and len(ba.app.meta.metascan.keyboards) > 1): ba.textwidget( parent=self._root_widget, h_align='center', position=(210, v - 70), size=(key_width * 6.1, key_height + 15), text=ba.Lstr( resource='keyboardChangeInstructionsText'), scale=0.75) btn2 = self._space_button btn3 = self._emoji_button ba.widget(edit=btn1, right_widget=btn2, left_widget=btn3) ba.widget(edit=btn2, left_widget=btn1, right_widget=self._done_button) ba.widget(edit=btn3, left_widget=btn1) ba.widget(edit=self._done_button, left_widget=btn2) ba.containerwidget(edit=self._root_widget, selected_child=self._char_keys[14]) self._refresh()
def _create_done(self, new_soundtrack: str) -> None: if new_soundtrack is not None: ba.playsound(ba.getsound('gunCocking')) self._refresh(select_soundtrack=new_soundtrack)
def on_popup_cancel(self) -> None: ba.playsound(ba.getsound('swish')) self._on_cancel()
def __init__(self) -> None: """Instantiate a BombFactory. You shouldn't need to do this; call bastd.actor.bomb.get_factory() to get a shared instance. """ self.bomb_model = ba.getmodel('bomb') self.sticky_bomb_model = ba.getmodel('bombSticky') self.impact_bomb_model = ba.getmodel('impactBomb') self.land_mine_model = ba.getmodel('landMine') self.tnt_model = ba.getmodel('tnt') self.regular_tex = ba.gettexture('bombColor') self.ice_tex = ba.gettexture('bombColorIce') self.sticky_tex = ba.gettexture('bombStickyColor') self.impact_tex = ba.gettexture('impactBombColor') self.impact_lit_tex = ba.gettexture('impactBombColorLit') self.land_mine_tex = ba.gettexture('landMine') self.land_mine_lit_tex = ba.gettexture('landMineLit') self.tnt_tex = ba.gettexture('tnt') self.hiss_sound = ba.getsound('hiss') self.debris_fall_sound = ba.getsound('debrisFall') self.wood_debris_fall_sound = ba.getsound('woodDebrisFall') self.explode_sounds = (ba.getsound('explosion01'), ba.getsound('explosion02'), ba.getsound('explosion03'), ba.getsound('explosion04'), ba.getsound('explosion05')) self.freeze_sound = ba.getsound('freeze') self.fuse_sound = ba.getsound('fuse01') self.activate_sound = ba.getsound('activateBeep') self.warn_sound = ba.getsound('warnBeep') # set up our material so new bombs don't collide with objects # that they are initially overlapping self.bomb_material = ba.Material() self.normal_sound_material = ba.Material() self.sticky_material = ba.Material() self.bomb_material.add_actions( conditions=((('we_are_younger_than', 100), 'or', ('they_are_younger_than', 100)), 'and', ('they_have_material', ba.sharedobj('object_material'))), actions=('modify_node_collision', 'collide', False)) # we want pickup materials to always hit us even if we're currently not # colliding with their node (generally due to the above rule) self.bomb_material.add_actions( conditions=('they_have_material', ba.sharedobj('pickup_material')), actions=('modify_part_collision', 'use_node_collide', False)) self.bomb_material.add_actions(actions=('modify_part_collision', 'friction', 0.3)) self.land_mine_no_explode_material = ba.Material() self.land_mine_blast_material = ba.Material() self.land_mine_blast_material.add_actions( conditions=(('we_are_older_than', 200), 'and', ('they_are_older_than', 200), 'and', ('eval_colliding', ), 'and', (('they_dont_have_material', self.land_mine_no_explode_material), 'and', (('they_have_material', ba.sharedobj('object_material')), 'or', ('they_have_material', ba.sharedobj('player_material'))))), actions=('message', 'our_node', 'at_connect', ImpactMessage())) self.impact_blast_material = ba.Material() self.impact_blast_material.add_actions( conditions=(('we_are_older_than', 200), 'and', ('they_are_older_than', 200), 'and', ('eval_colliding', ), 'and', (('they_have_material', ba.sharedobj('footing_material')), 'or', ('they_have_material', ba.sharedobj('object_material')))), actions=('message', 'our_node', 'at_connect', ImpactMessage())) self.blast_material = ba.Material() self.blast_material.add_actions( conditions=(('they_have_material', ba.sharedobj('object_material'))), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('message', 'our_node', 'at_connect', ExplodeHitMessage()))) self.dink_sounds = (ba.getsound('bombDrop01'), ba.getsound('bombDrop02')) self.sticky_impact_sound = ba.getsound('stickyImpact') self.roll_sound = ba.getsound('bombRoll01') # collision sounds self.normal_sound_material.add_actions( conditions=('they_have_material', ba.sharedobj('footing_material')), actions=(('impact_sound', self.dink_sounds, 2, 0.8), ('roll_sound', self.roll_sound, 3, 6))) self.sticky_material.add_actions(actions=(('modify_part_collision', 'stiffness', 0.1), ('modify_part_collision', 'damping', 1.0))) self.sticky_material.add_actions( conditions=(('they_have_material', ba.sharedobj('player_material')), 'or', ('they_have_material', ba.sharedobj('footing_material'))), actions=('message', 'our_node', 'at_connect', SplatMessage()))
def _no_favorite_selected_error(self) -> None: ba.screenmessage(ba.Lstr(resource='nothingIsSelectedErrorText'), color=(1, 0, 0)) ba.playsound(ba.getsound('error'))
def _no_replay_selected_error(self) -> None: ba.screenmessage(ba.Lstr(resource=self._r + '.noReplaySelectedErrorText'), color=(1, 0, 0)) ba.playsound(ba.getsound('error'))
def __init__(self, settings: dict): super().__init__(settings=settings) self._score_display_sound = ba.getsound('scoreHit01') self._score_display_sound_small = ba.getsound('scoreHit02') self._show_up_next: bool = True
def __init__(self, data: Dict[str, Any]): from ba.internal import is_browser_likely_available ba.set_analytics_screen('Friend Promo Code') self._width = 650 self._height = 400 super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), color=(0.45, 0.63, 0.15), transition='in_scale', scale=1.7 if ba.app.small_ui else 1.35 if ba.app.med_ui else 1.0)) self._data = copy.deepcopy(data) ba.playsound(ba.getsound('cashRegister')) ba.playsound(ba.getsound('swish')) self._cancel_button = ba.buttonwidget(parent=self._root_widget, scale=0.7, position=(50, self._height - 50), size=(60, 60), 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) ba.textwidget( parent=self._root_widget, position=(self._width * 0.5, self._height * 0.8), size=(0, 0), color=ba.app.infotextcolor, scale=1.0, flatness=1.0, h_align="center", v_align="center", text=ba.Lstr(resource='gatherWindow.shareThisCodeWithFriendsText'), maxwidth=self._width * 0.85) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height * 0.645), size=(0, 0), color=(1.0, 3.0, 1.0), scale=2.0, h_align="center", v_align="center", text=data['code'], maxwidth=self._width * 0.85) award_str: Optional[Union[str, ba.Lstr]] if self._data['awardTickets'] != 0: award_str = ba.Lstr( resource='gatherWindow.friendPromoCodeAwardText', subs=[('${COUNT}', str(self._data['awardTickets']))]) else: award_str = '' ba.textwidget( parent=self._root_widget, position=(self._width * 0.5, self._height * 0.37), size=(0, 0), color=ba.app.infotextcolor, scale=1.0, flatness=1.0, h_align="center", v_align="center", text=ba.Lstr( value='${A}\n${B}\n${C}\n${D}', subs=[ ('${A}', ba.Lstr( resource='gatherWindow.friendPromoCodeRedeemLongText', subs=[('${COUNT}', str(self._data['tickets'])), ('${MAX_USES}', str(self._data['usesRemaining']))])), ('${B}', ba.Lstr(resource=( 'gatherWindow.friendPromoCodeWhereToEnterText'))), ('${C}', award_str), ('${D}', ba.Lstr(resource='gatherWindow.friendPromoCodeExpireText', subs=[('${EXPIRE_HOURS}', str(self._data['expireHours']))])) ]), maxwidth=self._width * 0.9, max_height=self._height * 0.35) if is_browser_likely_available(): xoffs = 0 ba.buttonwidget(parent=self._root_widget, size=(200, 40), position=(self._width * 0.5 - 100 + xoffs, 39), autoselect=True, label=ba.Lstr(resource='gatherWindow.emailItText'), on_activate_call=ba.WeakCall(self._email))
def __init__(self, textwidget: ba.Widget, label: str, max_chars: int): # pylint: disable=too-many-locals self._target_text = textwidget self._width = 700 self._height = 400 uiscale = ba.app.uiscale top_extra = 20 if uiscale is ba.UIScale.SMALL else 0 super().__init__(root_widget=ba.containerwidget( parent=_ba.get_special_widget('overlay_stack'), size=(self._width, self._height + top_extra), transition='in_scale', scale_origin_stack_offset=self._target_text. get_screen_space_center(), scale=(2.0 if uiscale is ba.UIScale.SMALL else 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, 0) if uiscale is ba.UIScale.SMALL else ( 0, 0) if uiscale is ba.UIScale.MEDIUM else (0, 0))) self._done_button = ba.buttonwidget(parent=self._root_widget, position=(self._width - 200, 44), size=(140, 60), autoselect=True, label=ba.Lstr(resource='doneText'), on_activate_call=self._done) ba.containerwidget(edit=self._root_widget, on_cancel_call=self._cancel, start_button=self._done_button) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height - 41), size=(0, 0), scale=0.95, text=label, maxwidth=self._width - 140, color=ba.app.ui.title_color, h_align='center', v_align='center') self._text_field = ba.textwidget( parent=self._root_widget, position=(70, self._height - 116), max_chars=max_chars, text=cast(str, ba.textwidget(query=self._target_text)), on_return_press_call=self._done, autoselect=True, size=(self._width - 140, 55), v_align='center', editable=True, maxwidth=self._width - 175, force_internal_editing=True, always_show_carat=True) self._shift_button = None self._num_mode_button = None self._char_keys: List[ba.Widget] = [] self._mode = 'normal' v = self._height - 180 key_width = 46 key_height = 46 self._key_color_lit = (1.4, 1.2, 1.4) self._key_color = key_color = (0.69, 0.6, 0.74) self._key_color_dark = key_color_dark = (0.55, 0.55, 0.71) key_textcolor = (1, 1, 1) row_starts = (69, 95, 151) self._click_sound = ba.getsound('click01') # kill prev char keys for key in self._char_keys: key.delete() self._char_keys = [] # dummy data just used for row/column lengths... we don't actually # set things until refresh chars: List[Tuple[str, ...]] = [ ('q', 'u', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'), ('a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'), ('z', 'x', 'c', 'v', 'b', 'n', 'm') ] for row_num, row in enumerate(chars): h = row_starts[row_num] # shift key before row 3 if row_num == 2: self._shift_button = ba.buttonwidget( parent=self._root_widget, position=(h - key_width * 2.0, v), size=(key_width * 1.7, key_height), autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=ba.charstr(ba.SpecialChar.SHIFT), enable_sound=False, extra_touch_border_scale=0.3, button_type='square', ) for _ in row: btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(key_width, key_height), autoselect=True, enable_sound=False, textcolor=key_textcolor, color=key_color, label='', button_type='square', extra_touch_border_scale=0.1, ) self._char_keys.append(btn) h += key_width + 10 # Add delete key at end of third row. if row_num == 2: ba.buttonwidget(parent=self._root_widget, position=(h + 4, v), size=(key_width * 1.8, key_height), autoselect=True, enable_sound=False, repeat=True, textcolor=key_textcolor, color=key_color_dark, label=ba.charstr(ba.SpecialChar.DELETE), button_type='square', on_activate_call=self._del) v -= (key_height + 9) # Do space bar and stuff. if row_num == 2: if self._num_mode_button is None: self._num_mode_button = ba.buttonwidget( parent=self._root_widget, position=(112, v - 8), size=(key_width * 2, key_height + 5), enable_sound=False, button_type='square', extra_touch_border_scale=0.3, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label='', ) btn1 = self._num_mode_button btn2 = ba.buttonwidget(parent=self._root_widget, position=(210, v - 12), size=(key_width * 6.1, key_height + 15), extra_touch_border_scale=0.3, enable_sound=False, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=ba.Lstr(resource='spaceKeyText'), on_activate_call=ba.Call( self._type_char, ' ')) ba.widget(edit=btn1, right_widget=btn2) ba.widget(edit=btn2, left_widget=btn1, right_widget=self._done_button) ba.widget(edit=self._done_button, left_widget=btn2) ba.containerwidget(edit=self._root_widget, selected_child=self._char_keys[14]) self._refresh()
def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') self._tick_sound = ba.getsound('tick') self._countdownsounds = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_pos: Optional[Sequence[float]] = None self._flag_state: Optional[int] = None self._flag: Optional[stdflag.Flag] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[ReferenceType[ba.Team]] = None self._flag_region_material = ba.Material() self._flag_region_material.add_actions( conditions=('they_have_material', ba.sharedobj('player_material')), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', ba.Call(self._handle_player_flag_region_collide, True)), ('call', 'at_disconnect', ba.Call(self._handle_player_flag_region_collide, False))))
def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) if self.settings['Epic Mode']: self.slow_motion = True self._scoreboard = Scoreboard() self._chosen_one_player: Optional[ba.Player] = None self._swipsound = ba.getsound('swip') self._countdownsounds: Dict[int, ba.Sound] = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_spawn_pos: Optional[Sequence[float]] = None self._reset_region_material: Optional[ba.Material] = None self._flag: Optional[flag.Flag] = None self._reset_region: Optional[ba.Node] = None
def _smooth_update(self) -> None: # pylint: disable=too-many-branches # pylint: disable=too-many-statements try: if not self._button: return if self._ticking_node is None: with ba.Context('ui'): self._ticking_node = ba.newnode( 'sound', attrs={ 'sound': ba.getsound('scoreIncrease'), 'positional': False }) self._bg_flash = (not self._bg_flash) color_used = ((self._color[0] * 2, self._color[1] * 2, self._color[2] * 2) if self._bg_flash else self._color) textcolor_used = ((1, 1, 1) if self._bg_flash else self._textcolor) header_color_used = ((1, 1, 1) if self._bg_flash else self._header_color) if self._rank is not None: assert self._smooth_rank is not None self._smooth_rank -= 1.0 * self._smooth_increase_speed finished = (int(self._smooth_rank) <= self._rank) elif self._smooth_percent is not None: self._smooth_percent += 1.0 * self._smooth_increase_speed assert self._percent is not None finished = (int(self._smooth_percent) >= self._percent) else: finished = True if finished: if self._rank is not None: self._smooth_rank = float(self._rank) elif self._percent is not None: self._smooth_percent = float(self._percent) color_used = self._color textcolor_used = self._textcolor self._smooth_update_timer = None if self._ticking_node is not None: self._ticking_node.delete() self._ticking_node = None ba.playsound(ba.getsound('cashRegister2')) assert self._improvement_text is not None diff_text = ba.textwidget( parent=self._parent, size=(0, 0), h_align='center', v_align='center', text='+' + self._improvement_text + '!', position=(self._position[0] + self._size[0] * 0.5 * self._scale, self._position[1] + self._size[1] * -0.2 * self._scale), color=(0, 1, 0), flatness=1.0, shadow=0.0, scale=self._scale * 0.7) def safe_delete(widget: ba.Widget) -> None: if widget: widget.delete() ba.timer(2.0, ba.Call(safe_delete, diff_text), timetype=ba.TimeType.REAL) status_text: Union[str, ba.Lstr] if self._rank is not None: assert self._smooth_rank is not None status_text = ba.Lstr(resource='numberText', subs=[('${NUMBER}', str(int(self._smooth_rank)))]) elif self._smooth_percent is not None: status_text = str(int(self._smooth_percent)) + '%' else: status_text = '-' ba.textwidget(edit=self._value_text, text=status_text, color=textcolor_used) ba.textwidget(edit=self._title_text, color=header_color_used) ba.buttonwidget(edit=self._button, color=color_used) except Exception: ba.print_exception('Error doing smooth update.') self._smooth_update_timer = None
def __init__(self, settings: Dict[str, Any]): super().__init__(settings=settings) # Keep prev activity alive while we fade in. self.transition_time = 0.5 self._cymbal_sound = ba.getsound('cymbal')
def on_popup_cancel(self) -> None: ba.playsound(ba.getsound('swish')) self._transition_out()
def _tick_and_call(call: Optional[Callable[[Any], Any]], arg: Any) -> None: ba.playsound(ba.getsound('click01')) if call is not None: call(arg)
def _on_show_my_address_button_press(self, v2: float, container: Optional[ba.Widget], c_width: float) -> None: if not container: return tscl = 0.85 tspc = 25 ba.playsound(ba.getsound('swish')) ba.textwidget(parent=container, position=(c_width * 0.5 - 10, v2), color=(0.6, 1.0, 0.6), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, flatness=1.0, h_align='right', v_align='center', text=ba.Lstr(resource='gatherWindow.' 'manualYourLocalAddressText')) self._checking_state_text = ba.textwidget( parent=container, position=(c_width * 0.5, v2), color=(0.5, 0.5, 0.5), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, flatness=1.0, h_align='left', v_align='center', text=ba.Lstr(resource='gatherWindow.' 'checkingText')) threading.Thread(target=self._run_addr_fetch).start() v2 -= tspc ba.textwidget(parent=container, position=(c_width * 0.5 - 10, v2), color=(0.6, 1.0, 0.6), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, flatness=1.0, h_align='right', v_align='center', text=ba.Lstr(resource='gatherWindow.' 'manualYourAddressFromInternetText')) t_addr = ba.textwidget(parent=container, position=(c_width * 0.5, v2), color=(0.5, 0.5, 0.5), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, h_align='left', v_align='center', flatness=1.0, text=ba.Lstr(resource='gatherWindow.' 'checkingText')) v2 -= tspc ba.textwidget(parent=container, position=(c_width * 0.5 - 10, v2), color=(0.6, 1.0, 0.6), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, flatness=1.0, h_align='right', v_align='center', text=ba.Lstr(resource='gatherWindow.' 'manualJoinableFromInternetText')) t_accessible = ba.textwidget(parent=container, position=(c_width * 0.5, v2), color=(0.5, 0.5, 0.5), scale=tscl, size=(0, 0), maxwidth=c_width * 0.45, flatness=1.0, h_align='left', v_align='center', text=ba.Lstr(resource='gatherWindow.' 'checkingText')) v2 -= 28 t_accessible_extra = ba.textwidget(parent=container, position=(c_width * 0.5, v2), color=(1, 0.5, 0.2), scale=0.7, size=(0, 0), maxwidth=c_width * 0.9, flatness=1.0, h_align='center', v_align='center', text='') self._doing_access_check = False self._access_check_count = 0 # Cap our refreshes eventually. self._access_check_timer = ba.Timer( 10.0, ba.WeakCall(self._access_check_update, t_addr, t_accessible, t_accessible_extra), repeat=True, timetype=ba.TimeType.REAL) # Kick initial off. self._access_check_update(t_addr, t_accessible, t_accessible_extra) if self._check_button: self._check_button.delete()
def close_with_sound(self) -> None: """Close the window and make a lovely sound.""" ba.playsound(ba.getsound('swish')) self.close()
def _cancel(self) -> None: ba.playsound(ba.getsound('swish')) ba.containerwidget(edit=self._root_widget, transition='out_scale')
def _gamepad_event(self, control: str, event: Dict[str, Any], dialog: AwaitGamepadInputWindow) -> None: # pylint: disable=too-many-nested-blocks # pylint: disable=too-many-branches # pylint: disable=too-many-statements assert self._settings is not None ext = self._ext # For our dpad-buttons we're looking for either a button-press or a # hat-switch press. if control in [ 'buttonUp' + ext, 'buttonLeft' + ext, 'buttonDown' + ext, 'buttonRight' + ext ]: if event['type'] in ['BUTTONDOWN', 'HATMOTION']: # If its a button-down. if event['type'] == 'BUTTONDOWN': value = event['button'] self._settings[control] = value # If its a dpad. elif event['type'] == 'HATMOTION': # clear out any set dir-buttons for btn in [ 'buttonUp' + ext, 'buttonLeft' + ext, 'buttonRight' + ext, 'buttonDown' + ext ]: if btn in self._settings: del self._settings[btn] if event['hat'] == (2 if self._is_secondary else 1): # Exclude value in default case. if 'dpad' + ext in self._settings: del self._settings['dpad' + ext] else: self._settings['dpad' + ext] = event['hat'] # Update the 4 dpad button txt widgets. ba.textwidget(edit=self._textwidgets['buttonUp' + ext], text=self.get_control_value_name('buttonUp' + ext)) ba.textwidget(edit=self._textwidgets['buttonLeft' + ext], text=self.get_control_value_name('buttonLeft' + ext)) ba.textwidget(edit=self._textwidgets['buttonRight' + ext], text=self.get_control_value_name('buttonRight' + ext)) ba.textwidget(edit=self._textwidgets['buttonDown' + ext], text=self.get_control_value_name('buttonDown' + ext)) ba.playsound(ba.getsound('gunCocking')) dialog.die() elif control == 'analogStickLR' + ext: if event['type'] == 'AXISMOTION': # Ignore small values or else we might get triggered by noise. if abs(event['value']) > 0.5: axis = event['axis'] if axis == (5 if self._is_secondary else 1): # Exclude value in default case. if 'analogStickLR' + ext in self._settings: del self._settings['analogStickLR' + ext] else: self._settings['analogStickLR' + ext] = axis ba.textwidget( edit=self._textwidgets['analogStickLR' + ext], text=self.get_control_value_name('analogStickLR' + ext)) ba.playsound(ba.getsound('gunCocking')) dialog.die() # Now launch the up/down listener. AwaitGamepadInputWindow( self._input, 'analogStickUD' + ext, self._gamepad_event, ba.Lstr(resource=self._r + '.pressUpDownText')) elif control == 'analogStickUD' + ext: if event['type'] == 'AXISMOTION': # Ignore small values or else we might get triggered by noise. if abs(event['value']) > 0.5: axis = event['axis'] # Ignore our LR axis. if 'analogStickLR' + ext in self._settings: lr_axis = self._settings['analogStickLR' + ext] else: lr_axis = (5 if self._is_secondary else 1) if axis != lr_axis: if axis == (6 if self._is_secondary else 2): # Exclude value in default case. if 'analogStickUD' + ext in self._settings: del self._settings['analogStickUD' + ext] else: self._settings['analogStickUD' + ext] = axis ba.textwidget( edit=self._textwidgets['analogStickLR' + ext], text=self.get_control_value_name('analogStickLR' + ext)) ba.playsound(ba.getsound('gunCocking')) dialog.die() else: # For other buttons we just want a button-press. if event['type'] == 'BUTTONDOWN': value = event['button'] self._settings[control] = value # Update the button's text widget. ba.textwidget(edit=self._textwidgets[control], text=self.get_control_value_name(control)) ba.playsound(ba.getsound('gunCocking')) dialog.die()
def do_hit_at_position(self, pos: Sequence[float], player: Player) -> bool: """Handle a bomb hit at the given position.""" # pylint: disable=too-many-statements activity = self.activity # Ignore hits if the game is over or if we've already been hit if activity.has_ended() or self._hit or not self._nodes: return False diff = (ba.Vec3(pos) - self._position) # Disregard Y difference. Our target point probably isn't exactly # on the ground anyway. diff[1] = 0.0 dist = diff.length() bullseye = False if dist <= self._r3 + self._rfudge: # Inform our activity that we were hit self._hit = True activity.handlemessage(self.TargetHitMessage()) keys: Dict[float, Sequence[float]] = { 0.0: (1.0, 0.0, 0.0), 0.049: (1.0, 0.0, 0.0), 0.05: (1.0, 1.0, 1.0), 0.1: (0.0, 1.0, 0.0) } cdull = (0.3, 0.3, 0.3) popupcolor: Sequence[float] if dist <= self._r1 + self._rfudge: bullseye = True self._nodes[1].color = cdull self._nodes[2].color = cdull ba.animate_array(self._nodes[0], 'color', 3, keys, loop=True) popupscale = 1.8 popupcolor = (1, 1, 0, 1) streak = player.streak points = 10 + min(20, streak * 2) ba.playsound(ba.getsound('bellHigh')) if streak > 0: ba.playsound( ba.getsound( 'orchestraHit4' if streak > 3 else 'orchestraHit3' if streak > 2 else 'orchestraHit2' if streak > 1 else 'orchestraHit')) elif dist <= self._r2 + self._rfudge: self._nodes[0].color = cdull self._nodes[2].color = cdull ba.animate_array(self._nodes[1], 'color', 3, keys, loop=True) popupscale = 1.25 popupcolor = (1, 0.5, 0.2, 1) points = 4 ba.playsound(ba.getsound('bellMed')) else: self._nodes[0].color = cdull self._nodes[1].color = cdull ba.animate_array(self._nodes[2], 'color', 3, keys, loop=True) popupscale = 1.0 popupcolor = (0.8, 0.3, 0.3, 1) points = 2 ba.playsound(ba.getsound('bellLow')) # Award points/etc.. (technically should probably leave this up # to the activity). popupstr = '+' + str(points) # If there's more than 1 player in the game, include their # names and colors so they know who got the hit. if len(activity.players) > 1: popupcolor = ba.safecolor(player.color, target_intensity=0.75) popupstr += ' ' + player.getname() PopupText(popupstr, position=self._position, color=popupcolor, scale=popupscale).autoretain() # Give this player's team points and update the score-board. player.team.score += points assert isinstance(activity, TargetPracticeGame) activity.update_scoreboard() # Also give this individual player points # (only applies in teams mode). assert activity.stats is not None activity.stats.player_scored(player, points, showpoints=False, screenmessage=False) ba.animate_array(self._nodes[0], 'size', 1, { 0.8: self._nodes[0].size, 1.0: [0.0] }) ba.animate_array(self._nodes[1], 'size', 1, { 0.85: self._nodes[1].size, 1.05: [0.0] }) ba.animate_array(self._nodes[2], 'size', 1, { 0.9: self._nodes[2].size, 1.1: [0.0] }) ba.timer(1.1, ba.Call(self.handlemessage, ba.DieMessage())) return bullseye
def _duplicate_playlist(self) -> None: # pylint: disable=too-many-branches # pylint: disable=cyclic-import from ba.internal import have_pro_options from bastd.ui import purchase if not have_pro_options(): purchase.PurchaseWindow(items=['pro']) return if self._selected_playlist_name is None: return plst: Optional[List[Dict[str, Any]]] if self._selected_playlist_name == '__default__': plst = self._pvars.get_default_list_call() else: plst = ba.app.config[self._config_name_full].get( self._selected_playlist_name) if plst is None: ba.playsound(ba.getsound('error')) return # clamp at our max playlist number if len(ba.app.config[self._config_name_full]) > self._max_playlists: ba.screenmessage( ba.Lstr(translate=('serverResponses', 'Max number of playlists reached.')), color=(1, 0, 0)) ba.playsound(ba.getsound('error')) return copy_text = ba.Lstr(resource='copyOfText').evaluate() # get just 'Copy' or whatnot copy_word = copy_text.replace('${NAME}', '').strip() # find a valid dup name that doesn't exist test_index = 1 base_name = self._get_playlist_display_name( self._selected_playlist_name).evaluate() # If it looks like a copy, strip digits and spaces off the end. if copy_word in base_name: while base_name[-1].isdigit() or base_name[-1] == ' ': base_name = base_name[:-1] while True: if copy_word in base_name: test_name = base_name else: test_name = copy_text.replace('${NAME}', base_name) if test_index > 1: test_name += ' ' + str(test_index) if test_name not in ba.app.config[self._config_name_full]: break test_index += 1 _ba.add_transaction({ 'type': 'ADD_PLAYLIST', 'playlistType': self._pvars.config_name, 'playlistName': test_name, 'playlist': copy.deepcopy(plst) }) _ba.run_transactions() ba.playsound(ba.getsound('gunCocking')) self._refresh(select_playlist=test_name)
def __init__(self, offer: Dict[str, Any], transition: str = 'in_right'): # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals from ba.internal import (get_store_item_display_size, get_clean_price) from ba import SpecialChar from bastd.ui.store import item as storeitemui self._cancel_delay = offer.get('cancelDelay', 0) # First thing: if we're offering pro or an IAP, see if we have a # price for it. # If not, abort and go into zombie mode (the user should never see # us that way). real_price: Optional[str] # Misnomer: 'pro' actually means offer 'pro_sale'. if offer['item'] in ['pro', 'pro_fullprice']: real_price = _ba.get_price('pro' if offer['item'] == 'pro_fullprice' else 'pro_sale') if real_price is None and ba.app.debug_build: print('NOTE: Faking prices for debug build.') real_price = '$1.23' zombie = real_price is None elif isinstance(offer['price'], str): # (a string price implies IAP id) real_price = _ba.get_price(offer['price']) if real_price is None and ba.app.debug_build: print('NOTE: Faking price for debug build.') real_price = '$1.23' zombie = real_price is None else: real_price = None zombie = False if real_price is None: real_price = '?' if offer['item'] in ['pro', 'pro_fullprice']: self._offer_item = 'pro' else: self._offer_item = offer['item'] # If we wanted a real price but didn't find one, go zombie. if zombie: return # This can pop up suddenly, so lets block input for 1 second. _ba.lock_all_input() ba.timer(1.0, _ba.unlock_all_input, timetype=ba.TimeType.REAL) ba.playsound(ba.getsound('ding')) ba.timer(0.3, lambda: ba.playsound(ba.getsound('ooh')), timetype=ba.TimeType.REAL) self._offer = copy.deepcopy(offer) self._width = 580 self._height = 590 uiscale = ba.app.uiscale super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition=transition, scale=(1.2 if uiscale is ba.UIScale.SMALL else 1.15 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -15) if uiscale is ba.UIScale.SMALL else (0, 0))) self._is_bundle_sale = False try: if offer['item'] in ['pro', 'pro_fullprice']: original_price_str = _ba.get_price('pro') if original_price_str is None: original_price_str = '?' new_price_str = _ba.get_price('pro_sale') if new_price_str is None: new_price_str = '?' percent_off_text = '' else: # If the offer includes bonus tickets, it's a bundle-sale. if ('bonusTickets' in offer and offer['bonusTickets'] is not None): self._is_bundle_sale = True original_price = _ba.get_account_misc_read_val( 'price.' + self._offer_item, 9999) # For pure ticket prices we can show a percent-off. if isinstance(offer['price'], int): new_price = offer['price'] tchar = ba.charstr(SpecialChar.TICKET) original_price_str = tchar + str(original_price) new_price_str = tchar + str(new_price) percent_off = int( round(100.0 - (float(new_price) / original_price) * 100.0)) percent_off_text = ' ' + ba.Lstr( resource='store.salePercentText').evaluate().replace( '${PERCENT}', str(percent_off)) else: original_price_str = new_price_str = '?' percent_off_text = '' except Exception: print(f'Offer: {offer}') ba.print_exception('Error setting up special-offer') original_price_str = new_price_str = '?' percent_off_text = '' # If its a bundle sale, change the title. if self._is_bundle_sale: sale_text = ba.Lstr(resource='store.saleBundleText', fallback_resource='store.saleText').evaluate() else: # For full pro we say 'Upgrade?' since its not really a sale. if offer['item'] == 'pro_fullprice': sale_text = ba.Lstr( resource='store.upgradeQuestionText', fallback_resource='store.saleExclaimText').evaluate() else: sale_text = ba.Lstr( resource='store.saleExclaimText', fallback_resource='store.saleText').evaluate() self._title_text = ba.textwidget( parent=self._root_widget, position=(self._width * 0.5, self._height - 40), size=(0, 0), text=sale_text + ((' ' + ba.Lstr(resource='store.oneTimeOnlyText').evaluate()) if self._offer['oneTimeOnly'] else '') + percent_off_text, h_align='center', v_align='center', maxwidth=self._width * 0.9 - 220, scale=1.4, color=(0.3, 1, 0.3)) self._flash_on = False self._flashing_timer: Optional[ba.Timer] = ba.Timer( 0.05, ba.WeakCall(self._flash_cycle), repeat=True, timetype=ba.TimeType.REAL) ba.timer(0.6, ba.WeakCall(self._stop_flashing), timetype=ba.TimeType.REAL) size = get_store_item_display_size(self._offer_item) display: Dict[str, Any] = {} storeitemui.instantiate_store_item_display( self._offer_item, display, parent_widget=self._root_widget, b_pos=(self._width * 0.5 - size[0] * 0.5 + 10 - ((size[0] * 0.5 + 30) if self._is_bundle_sale else 0), self._height * 0.5 - size[1] * 0.5 + 20 + (20 if self._is_bundle_sale else 0)), b_width=size[0], b_height=size[1], button=not self._is_bundle_sale) # Wire up the parts we need. if self._is_bundle_sale: self._plus_text = ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height * 0.5 + 50), size=(0, 0), text='+', h_align='center', v_align='center', maxwidth=self._width * 0.9, scale=1.4, color=(0.5, 0.5, 0.5)) self._plus_tickets = ba.textwidget( parent=self._root_widget, position=(self._width * 0.5 + 120, self._height * 0.5 + 50), size=(0, 0), text=ba.charstr(SpecialChar.TICKET_BACKING) + str(offer['bonusTickets']), h_align='center', v_align='center', maxwidth=self._width * 0.9, scale=2.5, color=(0.2, 1, 0.2)) self._price_text = ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, 150), size=(0, 0), text=real_price, h_align='center', v_align='center', maxwidth=self._width * 0.9, scale=1.4, color=(0.2, 1, 0.2)) # Total-value if they supplied it. total_worth_item = offer.get('valueItem', None) if total_worth_item is not None: price = _ba.get_price(total_worth_item) total_worth_price = (get_clean_price(price) if price is not None else None) if total_worth_price is not None: total_worth_text = ba.Lstr(resource='store.totalWorthText', subs=[('${TOTAL_WORTH}', total_worth_price)]) self._total_worth_text = ba.textwidget( parent=self._root_widget, text=total_worth_text, position=(self._width * 0.5, 210), scale=0.9, maxwidth=self._width * 0.7, size=(0, 0), h_align='center', v_align='center', shadow=1.0, flatness=1.0, color=(0.3, 1, 1)) elif offer['item'] == 'pro_fullprice': # for full-price pro we simply show full price ba.textwidget(edit=display['price_widget'], text=real_price) ba.buttonwidget(edit=display['button'], on_activate_call=self._purchase) else: # Show old/new prices otherwise (for pro sale). ba.buttonwidget(edit=display['button'], on_activate_call=self._purchase) ba.imagewidget(edit=display['price_slash_widget'], opacity=1.0) ba.textwidget(edit=display['price_widget_left'], text=original_price_str) ba.textwidget(edit=display['price_widget_right'], text=new_price_str) # Add ticket button only if this is ticket-purchasable. if isinstance(offer.get('price'), int): self._get_tickets_button = ba.buttonwidget( parent=self._root_widget, position=(self._width - 125, self._height - 68), size=(90, 55), scale=1.0, button_type='square', color=(0.7, 0.5, 0.85), textcolor=(0.2, 1, 0.2), autoselect=True, label=ba.Lstr(resource='getTicketsWindow.titleText'), on_activate_call=self._on_get_more_tickets_press) self._ticket_text_update_timer = ba.Timer( 1.0, ba.WeakCall(self._update_tickets_text), timetype=ba.TimeType.REAL, repeat=True) self._update_tickets_text() self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, repeat=True) self._cancel_button = ba.buttonwidget( parent=self._root_widget, position=(50, 40) if self._is_bundle_sale else (self._width * 0.5 - 75, 40), size=(150, 60), scale=1.0, on_activate_call=self._cancel, autoselect=True, label=ba.Lstr(resource='noThanksText')) self._cancel_countdown_text = ba.textwidget( parent=self._root_widget, text='', position=(50 + 150 + 20, 40 + 27) if self._is_bundle_sale else (self._width * 0.5 - 75 + 150 + 20, 40 + 27), scale=1.1, size=(0, 0), h_align='left', v_align='center', shadow=1.0, flatness=1.0, color=(0.6, 0.5, 0.5)) self._update_cancel_button_graphics() if self._is_bundle_sale: self._purchase_button = ba.buttonwidget( parent=self._root_widget, position=(self._width - 200, 40), size=(150, 60), scale=1.0, on_activate_call=self._purchase, autoselect=True, label=ba.Lstr(resource='store.purchaseText')) ba.containerwidget(edit=self._root_widget, cancel_button=self._cancel_button, start_button=self._purchase_button if self._is_bundle_sale else None, selected_child=self._purchase_button if self._is_bundle_sale else display['button'])
def _print_already_own(self, charname: str) -> None: ba.screenmessage(ba.Lstr(resource=self._r + '.alreadyOwnText', subs=[('${NAME}', charname)]), color=(1, 0, 0)) ba.playsound(ba.getsound('error'))
def __init__(self, name: str, data: str, origin: Tuple[float, float] = (0.0, 0.0)): del origin # unused arg self._width = 450 self._height = 300 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.8 if uiscale is ba.UIScale.SMALL else 1.35 if uiscale is ba.UIScale.MEDIUM else 1.0))) ba.playsound(ba.getsound('cashRegister')) ba.playsound(ba.getsound('swish')) self._cancel_button = ba.buttonwidget(parent=self._root_widget, scale=0.7, position=(40, self._height - 40), 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) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height * 0.745), size=(0, 0), color=ba.app.ui.infotextcolor, scale=1.0, flatness=1.0, h_align='center', v_align='center', text=ba.Lstr(resource='exportSuccessText', subs=[('${NAME}', name)]), maxwidth=self._width * 0.85) ba.textwidget( parent=self._root_widget, position=(self._width * 0.5, self._height * 0.645), size=(0, 0), color=ba.app.ui.infotextcolor, scale=0.6, flatness=1.0, h_align='center', v_align='center', text=ba.Lstr(resource='importPlaylistCodeInstructionsText'), maxwidth=self._width * 0.85) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height * 0.4), size=(0, 0), color=(1.0, 3.0, 1.0), scale=2.3, h_align='center', v_align='center', text=data, maxwidth=self._width * 0.85)
def do_toggle(value: bool) -> None: ba.screenmessage( ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'), color=(1, 1, 0)) ba.playsound(ba.getsound('gunCocking')) _ba.set_low_level_config_value('enablexinput', not value)
def __init__(self) -> None: """Instantiate a FlagFactory. You shouldn't need to do this; call bastd.actor.flag.get_factory() to get a shared instance. """ shared = SharedObjects.get() self.flagmaterial = ba.Material() self.flagmaterial.add_actions( conditions=( ('we_are_younger_than', 100), 'and', ('they_have_material', shared.object_material), ), actions=('modify_node_collision', 'collide', False), ) self.flagmaterial.add_actions( conditions=( 'they_have_material', shared.footing_material, ), actions=( ('message', 'our_node', 'at_connect', 'footing', 1), ('message', 'our_node', 'at_disconnect', 'footing', -1), ), ) self.impact_sound = ba.getsound('metalHit') self.skid_sound = ba.getsound('metalSkid') self.flagmaterial.add_actions( conditions=( 'they_have_material', shared.footing_material, ), actions=( ('impact_sound', self.impact_sound, 2, 5), ('skid_sound', self.skid_sound, 2, 5), ), ) self.no_hit_material = ba.Material() self.no_hit_material.add_actions( conditions=( ('they_have_material', shared.pickup_material), 'or', ('they_have_material', shared.attack_material), ), actions=('modify_part_collision', 'collide', False), ) # We also don't want anything moving it. self.no_hit_material.add_actions( conditions=( ('they_have_material', shared.object_material), 'or', ('they_dont_have_material', shared.footing_material), ), actions=(('modify_part_collision', 'collide', False), ('modify_part_collision', 'physical', False)), ) self.flag_texture = ba.gettexture('flagColor')
def __init__(self, settings: dict): super().__init__(settings) self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') self._tick_sound = ba.getsound('tick') self._countdownsounds = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_spawn_pos: Optional[Sequence[float]] = None self._update_timer: Optional[ba.Timer] = None self._holding_players: List[Player] = [] self._flag_state: Optional[FlagState] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[Team] = None self._flag: Optional[Flag] = None self._hold_time = int(settings['Hold Time']) self._time_limit = float(settings['Time Limit'])