Ejemplo n.º 1
0
    def __init__(self) -> None:
        """Instantiate a factory object."""
        # pylint: disable=cyclic-import
        # FIXME: should probably put these somewhere common so we don't
        # have to import them from a module that imports us.
        from bastd.actor.spaz import (PickupMessage, PunchHitMessage,
                                      CurseExplodeMessage)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Lets load some basic rules.
        # (allows them to be tweaked from the master server)
        self.shield_decay_rate = _ba.get_account_misc_read_val('rsdr', 10.0)
        self.punch_cooldown = _ba.get_account_misc_read_val('rpc', 400)
        self.punch_cooldown_gloves = (_ba.get_account_misc_read_val(
            'rpcg', 300))
        self.punch_power_scale = _ba.get_account_misc_read_val('rpp', 1.2)
        self.punch_power_scale_gloves = (_ba.get_account_misc_read_val(
            'rppg', 1.4))
        self.max_shield_spillover_damage = (_ba.get_account_misc_read_val(
            'rsms', 500))
Ejemplo n.º 2
0
 def _cancel(self) -> None:
     if self._cancel_delay > 0:
         ba.playsound(ba.getsound('error'))
         return
     self._transition_out('out_right')
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
 def on_popup_cancel(self) -> None:
     ba.playsound(ba.getsound('swish'))
     self._on_cancel()
Ejemplo n.º 7
0
    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()))
Ejemplo n.º 8
0
 def _no_favorite_selected_error(self) -> None:
     ba.screenmessage(ba.Lstr(resource='nothingIsSelectedErrorText'),
                      color=(1, 0, 0))
     ba.playsound(ba.getsound('error'))
Ejemplo n.º 9
0
 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
Ejemplo n.º 11
0
    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))
Ejemplo n.º 12
0
    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()
Ejemplo n.º 13
0
    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))))
Ejemplo n.º 14
0
 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
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    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')
Ejemplo n.º 17
0
 def on_popup_cancel(self) -> None:
     ba.playsound(ba.getsound('swish'))
     self._transition_out()
Ejemplo n.º 18
0
 def _tick_and_call(call: Optional[Callable[[Any], Any]],
                    arg: Any) -> None:
     ba.playsound(ba.getsound('click01'))
     if call is not None:
         call(arg)
Ejemplo n.º 19
0
    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()
Ejemplo n.º 20
0
 def close_with_sound(self) -> None:
     """Close the window and make a lovely sound."""
     ba.playsound(ba.getsound('swish'))
     self.close()
Ejemplo n.º 21
0
 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()
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
    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)
Ejemplo n.º 25
0
    def __init__(self, offer: Dict[str, Any], transition: str = 'in_right'):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import (get_store_item_display_size, get_clean_price)
        from ba import SpecialChar
        from bastd.ui.store import item as storeitemui
        self._cancel_delay = offer.get('cancelDelay', 0)

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

        real_price: Optional[str]

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

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

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

        # This can pop up suddenly, so lets block input for 1 second.
        _ba.lock_all_input()
        ba.timer(1.0, _ba.unlock_all_input, timetype=ba.TimeType.REAL)
        ba.playsound(ba.getsound('ding'))
        ba.timer(0.3,
                 lambda: ba.playsound(ba.getsound('ooh')),
                 timetype=ba.TimeType.REAL)
        self._offer = copy.deepcopy(offer)
        self._width = 580
        self._height = 590
        uiscale = ba.app.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'])
Ejemplo n.º 26
0
 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'))
Ejemplo n.º 27
0
    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)
Ejemplo n.º 28
0
 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)
Ejemplo n.º 29
0
    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')
Ejemplo n.º 30
0
 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'])