Example #1
0
def get_tournament_prize_strings(entry: Dict[str, Any]) -> List[str]:
    """Given a tournament entry, return strings for its prize levels."""
    # pylint: disable=too-many-locals
    from ba._generated.enums import SpecialChar
    from ba._gameutils import get_trophy_string
    range1 = entry.get('prizeRange1')
    range2 = entry.get('prizeRange2')
    range3 = entry.get('prizeRange3')
    prize1 = entry.get('prize1')
    prize2 = entry.get('prize2')
    prize3 = entry.get('prize3')
    trophy_type_1 = entry.get('prizeTrophy1')
    trophy_type_2 = entry.get('prizeTrophy2')
    trophy_type_3 = entry.get('prizeTrophy3')
    out_vals = []
    for rng, prize, trophy_type in ((range1, prize1, trophy_type_1),
                                    (range2, prize2, trophy_type_2),
                                    (range3, prize3, trophy_type_3)):
        prval = ('' if rng is None else ('#' + str(rng[0])) if
                 (rng[0] == rng[1]) else
                 ('#' + str(rng[0]) + '-' + str(rng[1])))
        pvval = ''
        if trophy_type is not None:
            pvval += get_trophy_string(trophy_type)

        # If we've got trophies but not for this entry, throw some space
        # in to compensate so the ticket counts line up.
        if prize is not None:
            pvval = _ba.charstr(
                SpecialChar.TICKET_BACKING) + str(prize) + pvval
        out_vals.append(prval)
        out_vals.append(pvval)
    return out_vals
Example #2
0
    def __init__(self, lobby: ba.Lobby):
        from ba._nodeactor import NodeActor
        from ba._general import WeakCall
        self._state = 0
        self._press_to_punch: Union[str,
                                    ba.Lstr] = ('C' if _ba.app.iircade_mode
                                                else _ba.charstr(
                                                    SpecialChar.LEFT_BUTTON))
        self._press_to_bomb: Union[str,
                                   ba.Lstr] = ('B' if _ba.app.iircade_mode else
                                               _ba.charstr(
                                                   SpecialChar.RIGHT_BUTTON))
        self._joinmsg = Lstr(resource='pressAnyButtonToJoinText')
        can_switch_teams = (len(lobby.sessionteams) > 1)

        # If we have a keyboard, grab keys for punch and pickup.
        # FIXME: This of course is only correct on the local device;
        #  Should change this for net games.
        keyboard = _ba.getinputdevice('Keyboard', '#1', doraise=False)
        if keyboard is not None:
            self._update_for_keyboard(keyboard)

        flatness = 1.0 if _ba.app.vr_mode else 0.0
        self._text = NodeActor(
            _ba.newnode('text',
                        attrs={
                            'position': (0, -40),
                            'h_attach': 'center',
                            'v_attach': 'top',
                            'h_align': 'center',
                            'color': (0.7, 0.7, 0.95, 1.0),
                            'flatness': flatness,
                            'text': self._joinmsg
                        }))

        if _ba.app.demo_mode or _ba.app.arcade_mode:
            self._messages = [self._joinmsg]
        else:
            msg1 = Lstr(resource='pressToSelectProfileText',
                        subs=[
                            ('${BUTTONS}', _ba.charstr(SpecialChar.UP_ARROW) +
                             ' ' + _ba.charstr(SpecialChar.DOWN_ARROW))
                        ])
            msg2 = Lstr(resource='pressToOverrideCharacterText',
                        subs=[('${BUTTONS}', Lstr(resource='bombBoldText'))])
            msg3 = Lstr(value='${A} < ${B} >',
                        subs=[('${A}', msg2), ('${B}', self._press_to_bomb)])
            self._messages = (([
                Lstr(
                    resource='pressToSelectTeamText',
                    subs=[('${BUTTONS}', _ba.charstr(SpecialChar.LEFT_ARROW) +
                           ' ' + _ba.charstr(SpecialChar.RIGHT_ARROW))],
                )
            ] if can_switch_teams else []) + [msg1] + [msg3] + [self._joinmsg])

        self._timer = _ba.Timer(4.0, WeakCall(self._update), repeat=True)
Example #3
0
    def _getname(self, full: bool = False) -> str:
        name_raw = name = self._profilenames[self._profileindex]
        clamp = False
        if name == '_random':
            try:
                name = (
                    self._sessionplayer.inputdevice.get_default_player_name())
            except Exception:
                print_exception('Error getting _random chooser name.')
                name = 'Invalid'
            clamp = not full
        elif name == '__account__':
            try:
                name = self._sessionplayer.inputdevice.get_v1_account_name(
                    full)
            except Exception:
                print_exception('Error getting account name for chooser.')
                name = 'Invalid'
            clamp = not full
        elif name == '_edit':
            # Explicitly flattening this to a str; it's only relevant on
            # the host so that's ok.
            name = (Lstr(
                resource='createEditPlayerText',
                fallback_resource='editProfileWindow.titleNewText').evaluate())
        else:
            # If we have a regular profile marked as global with an icon,
            # use it (for full only).
            if full:
                try:
                    if self._profiles[name_raw].get('global', False):
                        icon = (self._profiles[name_raw]['icon']
                                if 'icon' in self._profiles[name_raw] else
                                _ba.charstr(SpecialChar.LOGO))
                        name = icon + name
                except Exception:
                    print_exception('Error applying global icon.')
            else:
                # We now clamp non-full versions of names so there's at
                # least some hope of reading them in-game.
                clamp = True

        if clamp:
            if len(name) > 10:
                name = name[:10] + '...'
        return name
Example #4
0
def _getname(self, full: bool = False) -> str:
    name_raw = name = self._profilenames[self._profileindex]
    if name[0] in self._glowing:
        name = name[1:]
        clamp = False
        if full:
            try:
                if self._profiles[name_raw].get('global', False):
                    icon = (self._profiles[name_raw]['icon']
                            if 'icon' in self._profiles[name_raw] else
                            _ba.charstr(SpecialChar.LOGO))
                    name = icon + name
            except Exception:
                print_exception('Error applying global icon.')
        else:
            clamp = True
        if clamp and len(name) > 10:
            name = name[:10] + '...'
        return name
    return self._getname_glowing(full)
Example #5
0
def get_player_profile_icon(profilename: str) -> str:
    """Given a profile name, returns an icon string for it.

    (non-account profiles only)
    """
    from ba._enums import SpecialChar

    bs_config = _ba.app.config
    icon: str
    try:
        is_global = bs_config['Player Profiles'][profilename]['global']
    except KeyError:
        is_global = False
    if is_global:
        try:
            icon = bs_config['Player Profiles'][profilename]['icon']
        except KeyError:
            icon = _ba.charstr(SpecialChar.LOGO)
    else:
        icon = ''
    return icon
    def _show_tip(self) -> None:
        # pylint: disable=too-many-locals
        from ba._gameutils import animate, GameTip
        from ba._enums import SpecialChar

        # If there's any tips left on the list, display one.
        if self.tips:
            tip = self.tips.pop(random.randrange(len(self.tips)))
            tip_title = Lstr(value='${A}:',
                             subs=[('${A}', Lstr(resource='tipText'))])
            icon: Optional[ba.Texture] = None
            sound: Optional[ba.Sound] = None
            if isinstance(tip, GameTip):
                icon = tip.icon
                sound = tip.sound
                tip = tip.text
                assert isinstance(tip, str)

            # Do a few substitutions.
            tip_lstr = Lstr(translate=('tips', tip),
                            subs=[('${PICKUP}',
                                   _ba.charstr(SpecialChar.TOP_BUTTON))])
            base_position = (75, 50)
            tip_scale = 0.8
            tip_title_scale = 1.2
            vrmode = _ba.app.vr_mode

            t_offs = -350.0
            tnode = _ba.newnode('text',
                                attrs={
                                    'text':
                                    tip_lstr,
                                    'scale':
                                    tip_scale,
                                    'maxwidth':
                                    900,
                                    'position': (base_position[0] + t_offs,
                                                 base_position[1]),
                                    'h_align':
                                    'left',
                                    'vr_depth':
                                    300,
                                    'shadow':
                                    1.0 if vrmode else 0.5,
                                    'flatness':
                                    1.0 if vrmode else 0.5,
                                    'v_align':
                                    'center',
                                    'v_attach':
                                    'bottom'
                                })
            t2pos = (base_position[0] + t_offs - (20 if icon is None else 82),
                     base_position[1] + 2)
            t2node = _ba.newnode('text',
                                 owner=tnode,
                                 attrs={
                                     'text': tip_title,
                                     'scale': tip_title_scale,
                                     'position': t2pos,
                                     'h_align': 'right',
                                     'vr_depth': 300,
                                     'shadow': 1.0 if vrmode else 0.5,
                                     'flatness': 1.0 if vrmode else 0.5,
                                     'maxwidth': 140,
                                     'v_align': 'center',
                                     'v_attach': 'bottom'
                                 })
            if icon is not None:
                ipos = (base_position[0] + t_offs - 40, base_position[1] + 1)
                img = _ba.newnode('image',
                                  attrs={
                                      'texture': icon,
                                      'position': ipos,
                                      'scale': (50, 50),
                                      'opacity': 1.0,
                                      'vr_depth': 315,
                                      'color': (1, 1, 1),
                                      'absolute_scale': True,
                                      'attach': 'bottomCenter'
                                  })
                animate(img, 'opacity', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0})
                _ba.timer(5.0, img.delete)
            if sound is not None:
                _ba.playsound(sound)

            combine = _ba.newnode('combine',
                                  owner=tnode,
                                  attrs={
                                      'input0': 1.0,
                                      'input1': 0.8,
                                      'input2': 1.0,
                                      'size': 4
                                  })
            combine.connectattr('output', tnode, 'color')
            combine.connectattr('output', t2node, 'color')
            animate(combine, 'input3', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0})
            _ba.timer(5.0, tnode.delete)
Example #7
0
def get_store_items() -> Dict[str, Dict]:
    """Returns info about purchasable items.

    (internal)
    """
    # pylint: disable=cyclic-import
    from ba._generated.enums import SpecialChar
    from bastd import maps
    if _ba.app.store_items is None:
        from bastd.game import ninjafight
        from bastd.game import meteorshower
        from bastd.game import targetpractice
        from bastd.game import easteregghunt

        # IMPORTANT - need to keep this synced with the master server.
        # (doing so manually for now)
        _ba.app.store_items = {
            'characters.kronk': {
                'character': 'Kronk'
            },
            'characters.zoe': {
                'character': 'Zoe'
            },
            'characters.jackmorgan': {
                'character': 'Jack Morgan'
            },
            'characters.mel': {
                'character': 'Mel'
            },
            'characters.snakeshadow': {
                'character': 'Snake Shadow'
            },
            'characters.bones': {
                'character': 'Bones'
            },
            'characters.bernard': {
                'character': 'Bernard',
                'highlight': (0.6, 0.5, 0.8)
            },
            'characters.pixie': {
                'character': 'Pixel'
            },
            'characters.wizard': {
                'character': 'Grumbledorf'
            },
            'characters.frosty': {
                'character': 'Frosty'
            },
            'characters.pascal': {
                'character': 'Pascal'
            },
            'characters.cyborg': {
                'character': 'B-9000'
            },
            'characters.agent': {
                'character': 'Agent Johnson'
            },
            'characters.taobaomascot': {
                'character': 'Taobao Mascot'
            },
            'characters.santa': {
                'character': 'Santa Claus'
            },
            'characters.bunny': {
                'character': 'Easter Bunny'
            },
            'pro': {},
            'maps.lake_frigid': {
                'map_type': maps.LakeFrigid
            },
            'games.ninja_fight': {
                'gametype': ninjafight.NinjaFightGame,
                'previewTex': 'courtyardPreview'
            },
            'games.meteor_shower': {
                'gametype': meteorshower.MeteorShowerGame,
                'previewTex': 'rampagePreview'
            },
            'games.target_practice': {
                'gametype': targetpractice.TargetPracticeGame,
                'previewTex': 'doomShroomPreview'
            },
            'games.easter_egg_hunt': {
                'gametype': easteregghunt.EasterEggHuntGame,
                'previewTex': 'towerDPreview'
            },
            'icons.flag_us': {
                'icon': _ba.charstr(SpecialChar.FLAG_UNITED_STATES)
            },
            'icons.flag_mexico': {
                'icon': _ba.charstr(SpecialChar.FLAG_MEXICO)
            },
            'icons.flag_germany': {
                'icon': _ba.charstr(SpecialChar.FLAG_GERMANY)
            },
            'icons.flag_brazil': {
                'icon': _ba.charstr(SpecialChar.FLAG_BRAZIL)
            },
            'icons.flag_russia': {
                'icon': _ba.charstr(SpecialChar.FLAG_RUSSIA)
            },
            'icons.flag_china': {
                'icon': _ba.charstr(SpecialChar.FLAG_CHINA)
            },
            'icons.flag_uk': {
                'icon': _ba.charstr(SpecialChar.FLAG_UNITED_KINGDOM)
            },
            'icons.flag_canada': {
                'icon': _ba.charstr(SpecialChar.FLAG_CANADA)
            },
            'icons.flag_india': {
                'icon': _ba.charstr(SpecialChar.FLAG_INDIA)
            },
            'icons.flag_japan': {
                'icon': _ba.charstr(SpecialChar.FLAG_JAPAN)
            },
            'icons.flag_france': {
                'icon': _ba.charstr(SpecialChar.FLAG_FRANCE)
            },
            'icons.flag_indonesia': {
                'icon': _ba.charstr(SpecialChar.FLAG_INDONESIA)
            },
            'icons.flag_italy': {
                'icon': _ba.charstr(SpecialChar.FLAG_ITALY)
            },
            'icons.flag_south_korea': {
                'icon': _ba.charstr(SpecialChar.FLAG_SOUTH_KOREA)
            },
            'icons.flag_netherlands': {
                'icon': _ba.charstr(SpecialChar.FLAG_NETHERLANDS)
            },
            'icons.flag_uae': {
                'icon': _ba.charstr(SpecialChar.FLAG_UNITED_ARAB_EMIRATES)
            },
            'icons.flag_qatar': {
                'icon': _ba.charstr(SpecialChar.FLAG_QATAR)
            },
            'icons.flag_egypt': {
                'icon': _ba.charstr(SpecialChar.FLAG_EGYPT)
            },
            'icons.flag_kuwait': {
                'icon': _ba.charstr(SpecialChar.FLAG_KUWAIT)
            },
            'icons.flag_algeria': {
                'icon': _ba.charstr(SpecialChar.FLAG_ALGERIA)
            },
            'icons.flag_saudi_arabia': {
                'icon': _ba.charstr(SpecialChar.FLAG_SAUDI_ARABIA)
            },
            'icons.flag_malaysia': {
                'icon': _ba.charstr(SpecialChar.FLAG_MALAYSIA)
            },
            'icons.flag_czech_republic': {
                'icon': _ba.charstr(SpecialChar.FLAG_CZECH_REPUBLIC)
            },
            'icons.flag_australia': {
                'icon': _ba.charstr(SpecialChar.FLAG_AUSTRALIA)
            },
            'icons.flag_singapore': {
                'icon': _ba.charstr(SpecialChar.FLAG_SINGAPORE)
            },
            'icons.flag_iran': {
                'icon': _ba.charstr(SpecialChar.FLAG_IRAN)
            },
            'icons.flag_poland': {
                'icon': _ba.charstr(SpecialChar.FLAG_POLAND)
            },
            'icons.flag_argentina': {
                'icon': _ba.charstr(SpecialChar.FLAG_ARGENTINA)
            },
            'icons.flag_philippines': {
                'icon': _ba.charstr(SpecialChar.FLAG_PHILIPPINES)
            },
            'icons.flag_chile': {
                'icon': _ba.charstr(SpecialChar.FLAG_CHILE)
            },
            'icons.fedora': {
                'icon': _ba.charstr(SpecialChar.FEDORA)
            },
            'icons.hal': {
                'icon': _ba.charstr(SpecialChar.HAL)
            },
            'icons.crown': {
                'icon': _ba.charstr(SpecialChar.CROWN)
            },
            'icons.yinyang': {
                'icon': _ba.charstr(SpecialChar.YIN_YANG)
            },
            'icons.eyeball': {
                'icon': _ba.charstr(SpecialChar.EYE_BALL)
            },
            'icons.skull': {
                'icon': _ba.charstr(SpecialChar.SKULL)
            },
            'icons.heart': {
                'icon': _ba.charstr(SpecialChar.HEART)
            },
            'icons.dragon': {
                'icon': _ba.charstr(SpecialChar.DRAGON)
            },
            'icons.helmet': {
                'icon': _ba.charstr(SpecialChar.HELMET)
            },
            'icons.mushroom': {
                'icon': _ba.charstr(SpecialChar.MUSHROOM)
            },
            'icons.ninja_star': {
                'icon': _ba.charstr(SpecialChar.NINJA_STAR)
            },
            'icons.viking_helmet': {
                'icon': _ba.charstr(SpecialChar.VIKING_HELMET)
            },
            'icons.moon': {
                'icon': _ba.charstr(SpecialChar.MOON)
            },
            'icons.spider': {
                'icon': _ba.charstr(SpecialChar.SPIDER)
            },
            'icons.fireball': {
                'icon': _ba.charstr(SpecialChar.FIREBALL)
            },
            'icons.mikirog': {
                'icon': _ba.charstr(SpecialChar.MIKIROG)
            },
        }
    store_items = _ba.app.store_items
    assert store_items is not None
    return store_items
Example #8
0
    def show_completion_banner(self, sound: bool = True) -> None:
        """Create the banner/sound for an acquired achievement announcement."""
        from ba import _account
        from ba import _gameutils
        from bastd.actor.text import Text
        from bastd.actor.image import Image
        from ba._general import WeakCall
        from ba._lang import Lstr
        from ba._messages import DieMessage
        from ba._enums import TimeType, SpecialChar
        app = _ba.app
        app.last_achievement_display_time = _ba.time(TimeType.REAL)

        # Just piggy-back onto any current activity
        # (should we use the session instead?..)
        activity = _ba.getactivity(doraise=False)

        # If this gets called while this achievement is occupying a slot
        # already, ignore it. (probably should never happen in real
        # life but whatevs).
        if self._completion_banner_slot is not None:
            return

        if activity is None:
            print('show_completion_banner() called with no current activity!')
            return

        if sound:
            _ba.playsound(_ba.getsound('achievement'), host_only=True)
        else:
            _ba.timer(
                0.5,
                lambda: _ba.playsound(_ba.getsound('ding'), host_only=True))

        in_time = 0.300
        out_time = 3.5

        base_vr_depth = 200

        # Find the first free slot.
        i = 0
        while True:
            if i not in app.achievement_completion_banner_slots:
                app.achievement_completion_banner_slots.add(i)
                self._completion_banner_slot = i

                # Remove us from that slot when we close.
                # Use a real-timer in the UI context so the removal runs even
                # if our activity/session dies.
                with _ba.Context('ui'):
                    _ba.timer(in_time + out_time,
                              self._remove_banner_slot,
                              timetype=TimeType.REAL)
                break
            i += 1
        assert self._completion_banner_slot is not None
        y_offs = 110 * self._completion_banner_slot
        objs: List[ba.Actor] = []
        obj = Image(_ba.gettexture('shadow'),
                    position=(-30, 30 + y_offs),
                    front=True,
                    attach=Image.Attach.BOTTOM_CENTER,
                    transition=Image.Transition.IN_BOTTOM,
                    vr_depth=base_vr_depth - 100,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    color=(0.0, 0.1, 0, 1),
                    scale=(1000, 300)).autoretain()
        objs.append(obj)
        assert obj.node
        obj.node.host_only = True
        obj = Image(_ba.gettexture('light'),
                    position=(-180, 60 + y_offs),
                    front=True,
                    attach=Image.Attach.BOTTOM_CENTER,
                    vr_depth=base_vr_depth,
                    transition=Image.Transition.IN_BOTTOM,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    color=(1.8, 1.8, 1.0, 0.0),
                    scale=(40, 300)).autoretain()
        objs.append(obj)
        assert obj.node
        obj.node.host_only = True
        obj.node.premultiplied = True
        combine = _ba.newnode('combine', owner=obj.node, attrs={'size': 2})
        _gameutils.animate(
            combine, 'input0', {
                in_time: 0,
                in_time + 0.4: 30,
                in_time + 0.5: 40,
                in_time + 0.6: 30,
                in_time + 2.0: 0
            })
        _gameutils.animate(
            combine, 'input1', {
                in_time: 0,
                in_time + 0.4: 200,
                in_time + 0.5: 500,
                in_time + 0.6: 200,
                in_time + 2.0: 0
            })
        combine.connectattr('output', obj.node, 'scale')
        _gameutils.animate(obj.node,
                           'rotate', {
                               0: 0.0,
                               0.35: 360.0
                           },
                           loop=True)
        obj = Image(self.get_icon_texture(True),
                    position=(-180, 60 + y_offs),
                    attach=Image.Attach.BOTTOM_CENTER,
                    front=True,
                    vr_depth=base_vr_depth - 10,
                    transition=Image.Transition.IN_BOTTOM,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    scale=(100, 100)).autoretain()
        objs.append(obj)
        assert obj.node
        obj.node.host_only = True

        # Flash.
        color = self.get_icon_color(True)
        combine = _ba.newnode('combine', owner=obj.node, attrs={'size': 3})
        keys = {
            in_time: 1.0 * color[0],
            in_time + 0.4: 1.5 * color[0],
            in_time + 0.5: 6.0 * color[0],
            in_time + 0.6: 1.5 * color[0],
            in_time + 2.0: 1.0 * color[0]
        }
        _gameutils.animate(combine, 'input0', keys)
        keys = {
            in_time: 1.0 * color[1],
            in_time + 0.4: 1.5 * color[1],
            in_time + 0.5: 6.0 * color[1],
            in_time + 0.6: 1.5 * color[1],
            in_time + 2.0: 1.0 * color[1]
        }
        _gameutils.animate(combine, 'input1', keys)
        keys = {
            in_time: 1.0 * color[2],
            in_time + 0.4: 1.5 * color[2],
            in_time + 0.5: 6.0 * color[2],
            in_time + 0.6: 1.5 * color[2],
            in_time + 2.0: 1.0 * color[2]
        }
        _gameutils.animate(combine, 'input2', keys)
        combine.connectattr('output', obj.node, 'color')

        obj = Image(_ba.gettexture('achievementOutline'),
                    model_transparent=_ba.getmodel('achievementOutline'),
                    position=(-180, 60 + y_offs),
                    front=True,
                    attach=Image.Attach.BOTTOM_CENTER,
                    vr_depth=base_vr_depth,
                    transition=Image.Transition.IN_BOTTOM,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    scale=(100, 100)).autoretain()
        assert obj.node
        obj.node.host_only = True

        # Flash.
        color = (2, 1.4, 0.4, 1)
        combine = _ba.newnode('combine', owner=obj.node, attrs={'size': 3})
        keys = {
            in_time: 1.0 * color[0],
            in_time + 0.4: 1.5 * color[0],
            in_time + 0.5: 6.0 * color[0],
            in_time + 0.6: 1.5 * color[0],
            in_time + 2.0: 1.0 * color[0]
        }
        _gameutils.animate(combine, 'input0', keys)
        keys = {
            in_time: 1.0 * color[1],
            in_time + 0.4: 1.5 * color[1],
            in_time + 0.5: 6.0 * color[1],
            in_time + 0.6: 1.5 * color[1],
            in_time + 2.0: 1.0 * color[1]
        }
        _gameutils.animate(combine, 'input1', keys)
        keys = {
            in_time: 1.0 * color[2],
            in_time + 0.4: 1.5 * color[2],
            in_time + 0.5: 6.0 * color[2],
            in_time + 0.6: 1.5 * color[2],
            in_time + 2.0: 1.0 * color[2]
        }
        _gameutils.animate(combine, 'input2', keys)
        combine.connectattr('output', obj.node, 'color')
        objs.append(obj)

        objt = Text(Lstr(value='${A}:',
                         subs=[('${A}', Lstr(resource='achievementText'))]),
                    position=(-120, 91 + y_offs),
                    front=True,
                    v_attach=Text.VAttach.BOTTOM,
                    vr_depth=base_vr_depth - 10,
                    transition=Text.Transition.IN_BOTTOM,
                    flatness=0.5,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    color=(1, 1, 1, 0.8),
                    scale=0.65).autoretain()
        objs.append(objt)
        assert objt.node
        objt.node.host_only = True

        objt = Text(self.display_name,
                    position=(-120, 50 + y_offs),
                    front=True,
                    v_attach=Text.VAttach.BOTTOM,
                    transition=Text.Transition.IN_BOTTOM,
                    vr_depth=base_vr_depth,
                    flatness=0.5,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    flash=True,
                    color=(1, 0.8, 0, 1.0),
                    scale=1.5).autoretain()
        objs.append(objt)
        assert objt.node
        objt.node.host_only = True

        objt = Text(_ba.charstr(SpecialChar.TICKET),
                    position=(-120 - 170 + 5, 75 + y_offs - 20),
                    front=True,
                    v_attach=Text.VAttach.BOTTOM,
                    h_align=Text.HAlign.CENTER,
                    v_align=Text.VAlign.CENTER,
                    transition=Text.Transition.IN_BOTTOM,
                    vr_depth=base_vr_depth,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    flash=True,
                    color=(0.5, 0.5, 0.5, 1),
                    scale=3.0).autoretain()
        objs.append(objt)
        assert objt.node
        objt.node.host_only = True

        objt = Text('+' + str(self.get_award_ticket_value()),
                    position=(-120 - 180 + 5, 80 + y_offs - 20),
                    v_attach=Text.VAttach.BOTTOM,
                    front=True,
                    h_align=Text.HAlign.CENTER,
                    v_align=Text.VAlign.CENTER,
                    transition=Text.Transition.IN_BOTTOM,
                    vr_depth=base_vr_depth,
                    flatness=0.5,
                    shadow=1.0,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    flash=True,
                    color=(0, 1, 0, 1),
                    scale=1.5).autoretain()
        objs.append(objt)
        assert objt.node
        objt.node.host_only = True

        # Add the 'x 2' if we've got pro.
        if _account.have_pro():
            objt = Text('x 2',
                        position=(-120 - 180 + 45, 80 + y_offs - 50),
                        v_attach=Text.VAttach.BOTTOM,
                        front=True,
                        h_align=Text.HAlign.CENTER,
                        v_align=Text.VAlign.CENTER,
                        transition=Text.Transition.IN_BOTTOM,
                        vr_depth=base_vr_depth,
                        flatness=0.5,
                        shadow=1.0,
                        transition_delay=in_time,
                        transition_out_delay=out_time,
                        flash=True,
                        color=(0.4, 0, 1, 1),
                        scale=0.9).autoretain()
            objs.append(objt)
            assert objt.node
            objt.node.host_only = True

        objt = Text(self.description_complete,
                    position=(-120, 30 + y_offs),
                    front=True,
                    v_attach=Text.VAttach.BOTTOM,
                    transition=Text.Transition.IN_BOTTOM,
                    vr_depth=base_vr_depth - 10,
                    flatness=0.5,
                    transition_delay=in_time,
                    transition_out_delay=out_time,
                    color=(1.0, 0.7, 0.5, 1.0),
                    scale=0.8).autoretain()
        objs.append(objt)
        assert objt.node
        objt.node.host_only = True

        for actor in objs:
            _ba.timer(out_time + 1.000,
                      WeakCall(actor.handlemessage, DieMessage()))
Example #9
0
    def create_display(self,
                       x: float,
                       y: float,
                       delay: float,
                       outdelay: float = None,
                       color: Sequence[float] = None,
                       style: str = 'post_game') -> List[ba.Actor]:
        """Create a display for the Achievement.

        Shows the Achievement icon, name, and description.
        """
        # pylint: disable=cyclic-import
        from ba._lang import Lstr
        from ba._enums import SpecialChar
        from ba._coopsession import CoopSession
        from bastd.actor.image import Image
        from bastd.actor.text import Text

        # Yeah this needs cleaning up.
        if style == 'post_game':
            in_game_colors = False
            in_main_menu = False
            h_attach = Text.HAttach.CENTER
            v_attach = Text.VAttach.CENTER
            attach = Image.Attach.CENTER
        elif style == 'in_game':
            in_game_colors = True
            in_main_menu = False
            h_attach = Text.HAttach.LEFT
            v_attach = Text.VAttach.TOP
            attach = Image.Attach.TOP_LEFT
        elif style == 'news':
            in_game_colors = True
            in_main_menu = True
            h_attach = Text.HAttach.CENTER
            v_attach = Text.VAttach.TOP
            attach = Image.Attach.TOP_CENTER
        else:
            raise ValueError('invalid style "' + style + '"')

        # Attempt to determine what campaign we're in
        # (so we know whether to show "hard mode only").
        if in_main_menu:
            hmo = False
        else:
            try:
                session = _ba.getsession()
                if isinstance(session, CoopSession):
                    campaign = session.campaign
                    assert campaign is not None
                    hmo = (self._hard_mode_only and campaign.name == 'Easy')
                else:
                    hmo = False
            except Exception:
                from ba import _error
                _error.print_exception('Error determining campaign')
                hmo = False

        objs: List[ba.Actor]

        if in_game_colors:
            objs = []
            out_delay_fin = (delay +
                             outdelay) if outdelay is not None else None
            if color is not None:
                cl1 = (2.0 * color[0], 2.0 * color[1], 2.0 * color[2],
                       color[3])
                cl2 = color
            else:
                cl1 = (1.5, 1.5, 2, 1.0)
                cl2 = (0.8, 0.8, 1.0, 1.0)

            if hmo:
                cl1 = (cl1[0], cl1[1], cl1[2], cl1[3] * 0.6)
                cl2 = (cl2[0], cl2[1], cl2[2], cl2[3] * 0.2)

            objs.append(
                Image(self.get_icon_texture(False),
                      host_only=True,
                      color=cl1,
                      position=(x - 25, y + 5),
                      attach=attach,
                      transition=Image.Transition.FADE_IN,
                      transition_delay=delay,
                      vr_depth=4,
                      transition_out_delay=out_delay_fin,
                      scale=(40, 40)).autoretain())
            txt = self.display_name
            txt_s = 0.85
            txt_max_w = 300
            objs.append(
                Text(txt,
                     host_only=True,
                     maxwidth=txt_max_w,
                     position=(x, y + 2),
                     transition=Text.Transition.FADE_IN,
                     scale=txt_s,
                     flatness=0.6,
                     shadow=0.5,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     color=cl2,
                     transition_delay=delay + 0.05,
                     transition_out_delay=out_delay_fin).autoretain())
            txt2_s = 0.62
            txt2_max_w = 400
            objs.append(
                Text(self.description_full
                     if in_main_menu else self.description,
                     host_only=True,
                     maxwidth=txt2_max_w,
                     position=(x, y - 14),
                     transition=Text.Transition.FADE_IN,
                     vr_depth=-5,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     scale=txt2_s,
                     flatness=1.0,
                     shadow=0.5,
                     color=cl2,
                     transition_delay=delay + 0.1,
                     transition_out_delay=out_delay_fin).autoretain())

            if hmo:
                txtactor = Text(
                    Lstr(resource='difficultyHardOnlyText'),
                    host_only=True,
                    maxwidth=txt2_max_w * 0.7,
                    position=(x + 60, y + 5),
                    transition=Text.Transition.FADE_IN,
                    vr_depth=-5,
                    h_attach=h_attach,
                    v_attach=v_attach,
                    h_align=Text.HAlign.CENTER,
                    v_align=Text.VAlign.CENTER,
                    scale=txt_s * 0.8,
                    flatness=1.0,
                    shadow=0.5,
                    color=(1, 1, 0.6, 1),
                    transition_delay=delay + 0.1,
                    transition_out_delay=out_delay_fin).autoretain()
                txtactor.node.rotate = 10
                objs.append(txtactor)

            # Ticket-award.
            award_x = -100
            objs.append(
                Text(_ba.charstr(SpecialChar.TICKET),
                     host_only=True,
                     position=(x + award_x + 33, y + 7),
                     transition=Text.Transition.FADE_IN,
                     scale=1.5,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     h_align=Text.HAlign.CENTER,
                     v_align=Text.VAlign.CENTER,
                     color=(1, 1, 1, 0.2 if hmo else 0.4),
                     transition_delay=delay + 0.05,
                     transition_out_delay=out_delay_fin).autoretain())
            objs.append(
                Text('+' + str(self.get_award_ticket_value()),
                     host_only=True,
                     position=(x + award_x + 28, y + 16),
                     transition=Text.Transition.FADE_IN,
                     scale=0.7,
                     flatness=1,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     h_align=Text.HAlign.CENTER,
                     v_align=Text.VAlign.CENTER,
                     color=cl2,
                     transition_delay=delay + 0.05,
                     transition_out_delay=out_delay_fin).autoretain())

        else:
            complete = self.complete
            objs = []
            c_icon = self.get_icon_color(complete)
            if hmo and not complete:
                c_icon = (c_icon[0], c_icon[1], c_icon[2], c_icon[3] * 0.3)
            objs.append(
                Image(self.get_icon_texture(complete),
                      host_only=True,
                      color=c_icon,
                      position=(x - 25, y + 5),
                      attach=attach,
                      vr_depth=4,
                      transition=Image.Transition.IN_RIGHT,
                      transition_delay=delay,
                      transition_out_delay=None,
                      scale=(40, 40)).autoretain())
            if complete:
                objs.append(
                    Image(_ba.gettexture('achievementOutline'),
                          host_only=True,
                          model_transparent=_ba.getmodel('achievementOutline'),
                          color=(2, 1.4, 0.4, 1),
                          vr_depth=8,
                          position=(x - 25, y + 5),
                          attach=attach,
                          transition=Image.Transition.IN_RIGHT,
                          transition_delay=delay,
                          transition_out_delay=None,
                          scale=(40, 40)).autoretain())
            else:
                if not complete:
                    award_x = -100
                    objs.append(
                        Text(_ba.charstr(SpecialChar.TICKET),
                             host_only=True,
                             position=(x + award_x + 33, y + 7),
                             transition=Text.Transition.IN_RIGHT,
                             scale=1.5,
                             h_attach=h_attach,
                             v_attach=v_attach,
                             h_align=Text.HAlign.CENTER,
                             v_align=Text.VAlign.CENTER,
                             color=(1, 1, 1, 0.4) if complete else
                             (1, 1, 1, (0.1 if hmo else 0.2)),
                             transition_delay=delay + 0.05,
                             transition_out_delay=None).autoretain())
                    objs.append(
                        Text('+' + str(self.get_award_ticket_value()),
                             host_only=True,
                             position=(x + award_x + 28, y + 16),
                             transition=Text.Transition.IN_RIGHT,
                             scale=0.7,
                             flatness=1,
                             h_attach=h_attach,
                             v_attach=v_attach,
                             h_align=Text.HAlign.CENTER,
                             v_align=Text.VAlign.CENTER,
                             color=((0.8, 0.93, 0.8, 1.0) if complete else
                                    (0.6, 0.6, 0.6, (0.2 if hmo else 0.4))),
                             transition_delay=delay + 0.05,
                             transition_out_delay=None).autoretain())

                    # Show 'hard-mode-only' only over incomplete achievements
                    # when that's the case.
                    if hmo:
                        txtactor = Text(
                            Lstr(resource='difficultyHardOnlyText'),
                            host_only=True,
                            maxwidth=300 * 0.7,
                            position=(x + 60, y + 5),
                            transition=Text.Transition.FADE_IN,
                            vr_depth=-5,
                            h_attach=h_attach,
                            v_attach=v_attach,
                            h_align=Text.HAlign.CENTER,
                            v_align=Text.VAlign.CENTER,
                            scale=0.85 * 0.8,
                            flatness=1.0,
                            shadow=0.5,
                            color=(1, 1, 0.6, 1),
                            transition_delay=delay + 0.05,
                            transition_out_delay=None).autoretain()
                        assert txtactor.node
                        txtactor.node.rotate = 10
                        objs.append(txtactor)

            objs.append(
                Text(self.display_name,
                     host_only=True,
                     maxwidth=300,
                     position=(x, y + 2),
                     transition=Text.Transition.IN_RIGHT,
                     scale=0.85,
                     flatness=0.6,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     color=((0.8, 0.93, 0.8, 1.0) if complete else
                            (0.6, 0.6, 0.6, (0.2 if hmo else 0.4))),
                     transition_delay=delay + 0.05,
                     transition_out_delay=None).autoretain())
            objs.append(
                Text(self.description_complete
                     if complete else self.description,
                     host_only=True,
                     maxwidth=400,
                     position=(x, y - 14),
                     transition=Text.Transition.IN_RIGHT,
                     vr_depth=-5,
                     h_attach=h_attach,
                     v_attach=v_attach,
                     scale=0.62,
                     flatness=1.0,
                     color=((0.6, 0.6, 0.6, 1.0) if complete else
                            (0.6, 0.6, 0.6, (0.2 if hmo else 0.4))),
                     transition_delay=delay + 0.1,
                     transition_out_delay=None).autoretain())
        return objs
def get_trophy_string(trophy_id: str) -> str:
    """Given a trophy id, returns a string to visualize it."""
    if trophy_id in TROPHY_CHARS:
        return _ba.charstr(TROPHY_CHARS[trophy_id])
    return '?'
Example #11
0
    def _build_host_tab(self) -> None:
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements

        if _ba.get_account_state() != 'signed_in':
            ba.textwidget(parent=self._container,
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          maxwidth=200,
                          scale=0.8,
                          color=(0.6, 0.56, 0.6),
                          position=(self._c_width * 0.5, self._c_height * 0.5),
                          text=ba.Lstr(resource='notSignedInErrorText'))
            self._showing_not_signed_in_screen = True
            return
        self._showing_not_signed_in_screen = False

        # At first we don't want to show anything until we've gotten a state.
        # Update: In this situation we now simply show our existing state
        # but give the start/stop button a loading message and disallow its
        # use. This keeps things a lot less jumpy looking and allows selecting
        # playlists/etc without having to wait for the server each time
        # back to the ui.
        if self._waiting_for_initial_state and bool(False):
            ba.textwidget(
                parent=self._container,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=200,
                scale=0.8,
                color=(0.6, 0.56, 0.6),
                position=(self._c_width * 0.5, self._c_height * 0.5),
                text=ba.Lstr(
                    value='${A}...',
                    subs=[('${A}', ba.Lstr(resource='store.loadingText'))],
                ),
            )
            return

        # If we're not currently hosting and hosting requires tickets,
        # Show our count (possibly with a link to purchase more).
        if (not self._waiting_for_initial_state
                and self._hostingstate.party_code is None
                and self._hostingstate.tickets_to_host_now != 0):
            if not ba.app.ui.use_toolbars:
                if ba.app.allow_ticket_purchases:
                    self._get_tickets_button = ba.buttonwidget(
                        parent=self._container,
                        position=(self._c_width - 210 + 125,
                                  self._c_height - 44),
                        autoselect=True,
                        scale=0.6,
                        size=(120, 60),
                        textcolor=(0.2, 1, 0.2),
                        label=ba.charstr(ba.SpecialChar.TICKET),
                        color=(0.65, 0.5, 0.8),
                        on_activate_call=self._on_get_tickets_press)
                else:
                    self._ticket_count_text = ba.textwidget(
                        parent=self._container,
                        scale=0.6,
                        position=(self._c_width - 210 + 125,
                                  self._c_height - 44),
                        color=(0.2, 1, 0.2),
                        h_align='center',
                        v_align='center')
                # Set initial ticket count.
                self._update_currency_ui()

        v = self._c_height - 90
        if self._hostingstate.party_code is None:
            ba.textwidget(
                parent=self._container,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=self._c_width * 0.9,
                scale=0.7,
                flatness=1.0,
                color=(0.5, 0.46, 0.5),
                position=(self._c_width * 0.5, v),
                text=ba.Lstr(
                    resource='gatherWindow.privatePartyCloudDescriptionText'))

        v -= 100
        if self._hostingstate.party_code is None:
            # We've got no current party running; show options to set one up.
            ba.textwidget(parent=self._container,
                          size=(0, 0),
                          h_align='right',
                          v_align='center',
                          maxwidth=200,
                          scale=0.8,
                          color=(0.6, 0.56, 0.6),
                          position=(self._c_width * 0.5 - 210, v),
                          text=ba.Lstr(resource='playlistText'))
            self._host_playlist_button = ba.buttonwidget(
                parent=self._container,
                size=(400, 70),
                color=(0.6, 0.5, 0.6),
                textcolor=(0.8, 0.75, 0.8),
                label=self._hostingconfig.playlist_name,
                on_activate_call=self._playlist_press,
                position=(self._c_width * 0.5 - 200, v - 35),
                up_widget=self._host_sub_tab_text,
                autoselect=True)

            # If it appears we're coming back from playlist selection,
            # re-select our playlist button.
            if ba.app.ui.selecting_private_party_playlist:
                ba.containerwidget(edit=self._container,
                                   selected_child=self._host_playlist_button)
                ba.app.ui.selecting_private_party_playlist = False
        else:
            # We've got a current party; show its info.
            ba.textwidget(
                parent=self._container,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=600,
                scale=0.9,
                color=(0.7, 0.64, 0.7),
                position=(self._c_width * 0.5, v + 90),
                text=ba.Lstr(resource='gatherWindow.partyServerRunningText'))
            ba.textwidget(parent=self._container,
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          maxwidth=600,
                          scale=0.7,
                          color=(0.7, 0.64, 0.7),
                          position=(self._c_width * 0.5, v + 50),
                          text=ba.Lstr(resource='gatherWindow.partyCodeText'))
            ba.textwidget(parent=self._container,
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          scale=2.0,
                          color=(0.0, 1.0, 0.0),
                          position=(self._c_width * 0.5, v + 10),
                          text=self._hostingstate.party_code)

            # Also action buttons to copy it and connect to it.
            if ba.clipboard_is_supported():
                cbtnoffs = 10
                self._host_copy_button = ba.buttonwidget(
                    parent=self._container,
                    size=(140, 40),
                    color=(0.6, 0.5, 0.6),
                    textcolor=(0.8, 0.75, 0.8),
                    label=ba.Lstr(resource='gatherWindow.copyCodeText'),
                    on_activate_call=self._host_copy_press,
                    position=(self._c_width * 0.5 - 150, v - 70),
                    autoselect=True)
            else:
                cbtnoffs = -70
            self._host_connect_button = ba.buttonwidget(
                parent=self._container,
                size=(140, 40),
                color=(0.6, 0.5, 0.6),
                textcolor=(0.8, 0.75, 0.8),
                label=ba.Lstr(resource='gatherWindow.manualConnectText'),
                on_activate_call=self._host_connect_press,
                position=(self._c_width * 0.5 + cbtnoffs, v - 70),
                autoselect=True)

        v -= 120

        # Line above the main action button:

        # If we don't want to show anything until we get a state:
        if self._waiting_for_initial_state:
            pass
        elif self._hostingstate.unavailable_error is not None:
            # If hosting is unavailable, show the associated reason.
            ba.textwidget(
                parent=self._container,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=self._c_width * 0.9,
                scale=0.7,
                flatness=1.0,
                color=(1.0, 0.0, 0.0),
                position=(self._c_width * 0.5, v),
                text=ba.Lstr(translate=('serverResponses',
                                        self._hostingstate.unavailable_error)))
        elif self._hostingstate.free_host_minutes_remaining is not None:
            # If we've been pre-approved to start/stop for free, show that.
            ba.textwidget(
                parent=self._container,
                size=(0, 0),
                h_align='center',
                v_align='center',
                maxwidth=self._c_width * 0.9,
                scale=0.7,
                flatness=1.0,
                color=((0.7, 0.64, 0.7) if self._hostingstate.party_code else
                       (0.0, 1.0, 0.0)),
                position=(self._c_width * 0.5, v),
                text=ba.Lstr(
                    resource='gatherWindow.startStopHostingMinutesText',
                    subs=[(
                        '${MINUTES}',
                        f'{self._hostingstate.free_host_minutes_remaining:.0f}'
                    )]))
        else:
            # Otherwise tell whether the free cloud server is available
            # or will be at some point.
            if self._hostingstate.party_code is None:
                if self._hostingstate.tickets_to_host_now == 0:
                    ba.textwidget(
                        parent=self._container,
                        size=(0, 0),
                        h_align='center',
                        v_align='center',
                        maxwidth=self._c_width * 0.9,
                        scale=0.7,
                        flatness=1.0,
                        color=(0.0, 1.0, 0.0),
                        position=(self._c_width * 0.5, v),
                        text=ba.Lstr(
                            resource=
                            'gatherWindow.freeCloudServerAvailableNowText'))
                else:
                    if self._hostingstate.minutes_until_free_host is None:
                        ba.textwidget(
                            parent=self._container,
                            size=(0, 0),
                            h_align='center',
                            v_align='center',
                            maxwidth=self._c_width * 0.9,
                            scale=0.7,
                            flatness=1.0,
                            color=(1.0, 0.6, 0.0),
                            position=(self._c_width * 0.5, v),
                            text=ba.Lstr(
                                resource=
                                'gatherWindow.freeCloudServerNotAvailableText')
                        )
                    else:
                        availmins = self._hostingstate.minutes_until_free_host
                        ba.textwidget(
                            parent=self._container,
                            size=(0, 0),
                            h_align='center',
                            v_align='center',
                            maxwidth=self._c_width * 0.9,
                            scale=0.7,
                            flatness=1.0,
                            color=(1.0, 0.6, 0.0),
                            position=(self._c_width * 0.5, v),
                            text=ba.Lstr(resource='gatherWindow.'
                                         'freeCloudServerAvailableMinutesText',
                                         subs=[('${MINUTES}',
                                                f'{availmins:.0f}')]))

        v -= 100

        if (self._waiting_for_start_stop_response
                or self._waiting_for_initial_state):
            btnlabel = ba.Lstr(resource='oneMomentText')
        else:
            if self._hostingstate.unavailable_error is not None:
                btnlabel = ba.Lstr(
                    resource='gatherWindow.hostingUnavailableText')
            elif self._hostingstate.party_code is None:
                ticon = _ba.charstr(ba.SpecialChar.TICKET)
                nowtickets = self._hostingstate.tickets_to_host_now
                if nowtickets > 0:
                    btnlabel = ba.Lstr(
                        resource='gatherWindow.startHostingPaidText',
                        subs=[('${COST}', f'{ticon}{nowtickets}')])
                else:
                    btnlabel = ba.Lstr(
                        resource='gatherWindow.startHostingText')
            else:
                btnlabel = ba.Lstr(resource='gatherWindow.stopHostingText')

        disabled = (self._hostingstate.unavailable_error is not None
                    or self._waiting_for_initial_state)
        waiting = self._waiting_for_start_stop_response
        self._host_start_stop_button = ba.buttonwidget(
            parent=self._container,
            size=(400, 80),
            color=((0.6, 0.6, 0.6) if disabled else
                   (0.5, 1.0, 0.5) if waiting else None),
            enable_sound=False,
            label=btnlabel,
            textcolor=((0.7, 0.7, 0.7) if disabled else None),
            position=(self._c_width * 0.5 - 200, v),
            on_activate_call=self._start_stop_button_press,
            autoselect=True)
Example #12
0
    def _get_name(self, full: bool = False) -> str:
        # FIXME: Needs cleanup.
        # pylint: disable=too-many-branches
        from ba._lang import Lstr
        from ba._enums import SpecialChar
        name_raw = name = self._profilenames[self._profileindex]
        clamp = False
        if name == '_random':
            input_device: Optional[ba.InputDevice]
            try:
                input_device = self._player.get_input_device()
            except Exception:
                input_device = None
            if input_device is not None:
                name = input_device.get_default_player_name()
            else:
                name = 'Invalid'
            if not full:
                clamp = True
        elif name == '__account__':
            try:
                input_device = self._player.get_input_device()
            except Exception:
                input_device = None
            if input_device is not None:
                name = input_device.get_account_name(full)
            else:
                name = 'Invalid'
            if not full:
                clamp = True
        elif name == '_edit':
            # FIXME: This causes problems as an Lstr, but its ok to
            #  explicitly translate for now since this is only shown on the
            #  host. (also should elaborate; don't remember what problems this
            #  caused)
            name = (Lstr(
                resource='createEditPlayerText',
                fallback_resource='editProfileWindow.titleNewText').evaluate())
        else:

            # If we have a regular profile marked as global with an icon,
            # use it (for full only).
            if full:
                try:
                    if self.profiles[name_raw].get('global', False):
                        icon = (self.profiles[name_raw]['icon']
                                if 'icon' in self.profiles[name_raw] else
                                _ba.charstr(SpecialChar.LOGO))
                        name = icon + name
                except Exception:
                    from ba import _error
                    _error.print_exception('Error applying global icon')
            else:

                # We now clamp non-full versions of names so there's at
                # least some hope of reading them in-game.
                clamp = True

        if clamp:
            if len(name) > 10:
                name = name[:10] + '...'
        return name
Example #13
0
    def __init__(self, lobby: ba.Lobby):
        # pylint: disable=too-many-locals
        from ba import _input
        from ba._lang import Lstr
        from ba._nodeactor import NodeActor
        from ba._general import WeakCall
        from ba._enums import SpecialChar
        can_switch_teams = (len(lobby.teams) > 1)
        self._state = 0
        press_to_punch: Union[str,
                              ba.Lstr] = _ba.charstr(SpecialChar.LEFT_BUTTON)
        press_to_bomb: Union[str,
                             ba.Lstr] = _ba.charstr(SpecialChar.RIGHT_BUTTON)

        # If we have a keyboard, grab keys for punch and pickup.
        # FIXME: This of course is only correct on the local device;
        #  Should change this for net games.
        keyboard: Optional[ba.InputDevice] = _ba.get_input_device(
            'Keyboard', '#1', doraise=False)
        if keyboard is not None:
            punch_key = keyboard.get_button_name(
                _input.get_device_value(keyboard, 'buttonPunch'))
            press_to_punch = Lstr(resource='orText',
                                  subs=[('${A}',
                                         Lstr(value='\'${K}\'',
                                              subs=[('${K}', punch_key)])),
                                        ('${B}', press_to_punch)])
            bomb_key = keyboard.get_button_name(
                _input.get_device_value(keyboard, 'buttonBomb'))
            press_to_bomb = Lstr(resource='orText',
                                 subs=[('${A}',
                                        Lstr(value='\'${K}\'',
                                             subs=[('${K}', bomb_key)])),
                                       ('${B}', press_to_bomb)])
            join_str = Lstr(value='${A} < ${B} >',
                            subs=[('${A}',
                                   Lstr(resource='pressPunchToJoinText')),
                                  ('${B}', press_to_punch)])
        else:
            join_str = Lstr(resource='pressAnyButtonToJoinText')

        flatness = 1.0 if _ba.app.vr_mode else 0.0
        self._text = NodeActor(
            _ba.newnode('text',
                        attrs={
                            'position': (0, -40),
                            'h_attach': 'center',
                            'v_attach': 'top',
                            'h_align': 'center',
                            'color': (0.7, 0.7, 0.95, 1.0),
                            'flatness': flatness,
                            'text': join_str
                        }))

        if _ba.app.kiosk_mode:
            self._messages = [join_str]
        else:
            msg1 = Lstr(resource='pressToSelectProfileText',
                        subs=[
                            ('${BUTTONS}', _ba.charstr(SpecialChar.UP_ARROW) +
                             ' ' + _ba.charstr(SpecialChar.DOWN_ARROW))
                        ])
            msg2 = Lstr(resource='pressToOverrideCharacterText',
                        subs=[('${BUTTONS}', Lstr(resource='bombBoldText'))])
            msg3 = Lstr(value='${A} < ${B} >',
                        subs=[('${A}', msg2), ('${B}', press_to_bomb)])
            self._messages = (([
                Lstr(resource='pressToSelectTeamText',
                     subs=[('${BUTTONS}', _ba.charstr(SpecialChar.LEFT_ARROW) +
                            ' ' + _ba.charstr(SpecialChar.RIGHT_ARROW))])
            ] if can_switch_teams else []) + [msg1] + [msg3] + [join_str])

        self._timer = _ba.Timer(4.0, WeakCall(self._update), repeat=True)