Exemple #1
0
def get_human_readable_user_scripts_path() -> str:
    """Return a human readable location of user-scripts.

    This is NOT a valid filesystem path; may be something like "(SD Card)".
    """
    from ba import _lang
    app = _ba.app
    path: Optional[str] = app.user_scripts_directory
    if path is None:
        return '<Not Available>'

    # On newer versions of android, the user's external storage dir is probably
    # only visible to the user's processes and thus not really useful printed
    # in its entirety; lets print it as <External Storage>/myfilepath.
    if app.platform == 'android':
        ext_storage_path: Optional[str] = (
            _ba.android_get_external_storage_path())
        if (ext_storage_path is not None
                and app.user_scripts_directory.startswith(ext_storage_path)):
            path = ('<' +
                    _lang.Lstr(resource='externalStorageText').evaluate() +
                    '>' + app.user_scripts_directory[len(ext_storage_path):])
    return path
Exemple #2
0
    def _on_play_folder_cb(self,
                           result: Union[str, List[str]],
                           error: Optional[str] = None) -> None:
        from ba import _lang
        if error is not None:
            rstr = (_lang.Lstr(
                resource='internal.errorPlayingMusicText').evaluate())
            if isinstance(result, str):
                err_str = (rstr.replace('${MUSIC}', os.path.basename(result)) +
                           '; ' + str(error))
            else:
                err_str = (rstr.replace('${MUSIC}', '<multiple>') + '; ' +
                           str(error))
            _ba.screenmessage(err_str, color=(1, 0, 0))
            return

        # There's a chance a stop could have been issued before our thread
        # returned. If that's the case, don't play.
        if not self._want_to_play:
            print('_on_play_folder_cb called with _want_to_play False')
        else:
            self._actually_playing = True
            _ba.music_player_play(result)
Exemple #3
0
 def _show_remaining_achievements(self) -> None:
     # pylint: disable=cyclic-import
     from ba import _achievement
     from ba import _lang
     from bastd.actor.text import Text
     ts_h_offs = 30
     v_offs = -200
     achievements = [
         a for a in _achievement.get_achievements_for_coop_level(
             self._get_coop_level_name()) if not a.complete
     ]
     vrmode = _ba.app.vr_mode
     if achievements:
         Text(_lang.Lstr(resource='achievementsRemainingText'),
              host_only=True,
              position=(ts_h_offs - 10 + 40, v_offs - 10),
              transition=Text.Transition.FADE_IN,
              scale=1.1,
              h_attach=Text.HAttach.LEFT,
              v_attach=Text.VAttach.TOP,
              color=(1, 1, 1.2, 1) if vrmode else (0.8, 0.8, 1.0, 1.0),
              flatness=1.0 if vrmode else 0.6,
              shadow=1.0 if vrmode else 0.5,
              transition_delay=0.0,
              transition_out_delay=1.3
              if self.slow_motion else 4.0).autoretain()
         hval = 70
         vval = -50
         tdelay = 0.0
         for ach in achievements:
             tdelay += 0.05
             ach.create_display(hval + 40,
                                vval + v_offs,
                                0 + tdelay,
                                outdelay=1.3 if self.slow_motion else 4.0,
                                style='in_game')
             vval -= 55
Exemple #4
0
def get_remote_app_name() -> ba.Lstr:
    """(internal)"""
    from ba import _lang
    return _lang.Lstr(resource='remote_app.app_name')
Exemple #5
0
    def __init__(self, vpos: float, player: _ba.SessionPlayer,
                 lobby: 'Lobby') -> None:
        # FIXME: Tidy up around here.
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        from ba import _gameutils
        from ba import _profile
        from ba import _lang
        app = _ba.app
        self._deek_sound = _ba.getsound('deek')
        self._click_sound = _ba.getsound('click01')
        self._punchsound = _ba.getsound('punch01')
        self._swish_sound = _ba.getsound('punchSwish')
        self._errorsound = _ba.getsound('error')
        self._mask_texture = _ba.gettexture('characterIconMask')
        self._vpos = vpos
        self._lobby = weakref.ref(lobby)
        self._player = player
        self._inited = False
        self._dead = False
        self._text_node: Optional[ba.Node] = None
        self._profilename = ''
        self._profilenames: List[str] = []
        self._ready: bool = False
        self.character_names: List[str] = []
        self.last_change: Sequence[Union[float, int]] = (0, 0)

        # Hmm does this need to be public?
        self.profiles: Dict[str, Dict[str, Any]] = {}

        # Load available profiles either from the local config or from the
        # remote device.
        self.reload_profiles()

        # Note: this is just our local index out of available teams; *not*
        # the team-id!
        self._selected_team_index: int = self.lobby.next_add_team

        # Store a persistent random character index; we'll use this for the
        # '_random' profile. Let's use their input_device id to seed it. This
        # will give a persistent character for them between games and will
        # distribute characters nicely if everyone is random.
        try:
            input_device_id = self._player.get_input_device().id
        except Exception:
            from ba import _error
            _error.print_exception('Error getting device-id on chooser create')
            input_device_id = 0

        if app.lobby_random_char_index_offset is None:

            # We want the first device that asks for a chooser to always get
            # spaz as a random character..
            # scratch that.. we now kinda accomplish the same thing with
            # account profiles so lets just be fully random here.
            app.lobby_random_char_index_offset = (random.randrange(1000))

        # To calc our random index we pick a random character out of our
        # unlocked list and then locate that character's index in the full
        # list.
        char_index_offset = app.lobby_random_char_index_offset
        assert char_index_offset is not None
        self._random_character_index = ((input_device_id + char_index_offset) %
                                        len(self.character_names))
        self._random_color, self._random_highlight = (
            _profile.get_player_profile_colors(None))

        # Attempt to pick an initial profile based on what's been stored
        # for this input device.
        input_device = self._player.get_input_device()
        try:
            name = input_device.name
            unique_id = input_device.unique_identifier
            self._profilename = (
                app.config['Default Player Profiles'][name + ' ' + unique_id])
            self._profileindex = self._profilenames.index(self._profilename)

            # If this one is __account__ and is local and we haven't marked
            # anyone as the account-profile device yet, mark this guy as it.
            # (prevents the next joiner from getting the account profile too).
            if (self._profilename == '__account__'
                    and not input_device.is_remote_client
                    and app.lobby_account_profile_device_id is None):
                app.lobby_account_profile_device_id = input_device_id

        # Well hmm that didn't work.. pick __account__, _random, or some
        # other random profile.
        except Exception:

            profilenames = self._profilenames

            # We want the first local input-device in the game to latch on to
            # the account profile.
            if (not input_device.is_remote_client
                    and not input_device.is_controller_app):
                if (app.lobby_account_profile_device_id is None
                        and '__account__' in profilenames):
                    app.lobby_account_profile_device_id = input_device_id

            # If this is the designated account-profile-device, try to default
            # to the account profile.
            if (input_device_id == app.lobby_account_profile_device_id
                    and '__account__' in profilenames):
                self._profileindex = profilenames.index('__account__')
            else:

                # If this is the controller app, it defaults to using a random
                # profile (since we can pull the random name from the app).
                if input_device.is_controller_app:
                    self._profileindex = profilenames.index('_random')
                else:

                    # If its a client connection, for now just force
                    # the account profile if possible.. (need to provide a
                    # way for clients to specify/remember their default
                    # profile on remote servers that do not already know them).
                    if (input_device.is_remote_client
                            and '__account__' in profilenames):
                        self._profileindex = profilenames.index('__account__')
                    else:

                        # Cycle through our non-random profiles once; after
                        # that, everyone gets random.
                        while (app.lobby_random_profile_index <
                               len(profilenames)
                               and profilenames[app.lobby_random_profile_index]
                               in ('_random', '__account__', '_edit')):
                            app.lobby_random_profile_index += 1
                        if (app.lobby_random_profile_index <
                                len(profilenames)):
                            self._profileindex = (
                                app.lobby_random_profile_index)
                            app.lobby_random_profile_index += 1
                        else:
                            self._profileindex = profilenames.index('_random')

            self._profilename = profilenames[self._profileindex]

        self.character_index = self._random_character_index
        self._color = self._random_color
        self._highlight = self._random_highlight
        self._text_node = _ba.newnode('text',
                                      delegate=self,
                                      attrs={
                                          'position': (-100, self._vpos),
                                          'maxwidth': 160,
                                          'shadow': 0.5,
                                          'vr_depth': -20,
                                          'h_align': 'left',
                                          'v_align': 'center',
                                          'v_attach': 'top'
                                      })

        _gameutils.animate(self._text_node, 'scale', {0: 0, 0.1: 1.0})
        self.icon = _ba.newnode('image',
                                owner=self._text_node,
                                attrs={
                                    'position': (-130, self._vpos + 20),
                                    'mask_texture': self._mask_texture,
                                    'vr_depth': -10,
                                    'attach': 'topCenter'
                                })

        _gameutils.animate_array(self.icon, 'scale', 2, {
            0: (0, 0),
            0.1: (45, 45)
        })

        self._set_ready(False)

        # Set our initial name to '<choosing player>' in case anyone asks.
        self._player.set_name(
            _lang.Lstr(resource='choosingPlayerText').evaluate(), real=False)

        self.update_from_player_profiles()
        self.update_position()
        self._inited = True