bastd.activity.multiteamscore

Functionality related to teams mode score screen.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Functionality related to teams mode score screen."""
  4from __future__ import annotations
  5
  6from typing import TYPE_CHECKING
  7
  8import ba
  9from ba.internal import ScoreScreenActivity
 10from bastd.actor.text import Text
 11from bastd.actor.image import Image
 12
 13if TYPE_CHECKING:
 14    pass
 15
 16
 17class MultiTeamScoreScreenActivity(ScoreScreenActivity):
 18    """Base class for score screens."""
 19
 20    def __init__(self, settings: dict):
 21        super().__init__(settings=settings)
 22        self._score_display_sound = ba.getsound('scoreHit01')
 23        self._score_display_sound_small = ba.getsound('scoreHit02')
 24
 25        self._show_up_next: bool = True
 26
 27    def on_begin(self) -> None:
 28        super().on_begin()
 29        session = self.session
 30        if self._show_up_next and isinstance(session, ba.MultiTeamSession):
 31            txt = ba.Lstr(
 32                value='${A}   ${B}',
 33                subs=[
 34                    (
 35                        '${A}',
 36                        ba.Lstr(
 37                            resource='upNextText',
 38                            subs=[
 39                                ('${COUNT}', str(session.get_game_number() + 1))
 40                            ],
 41                        ),
 42                    ),
 43                    ('${B}', session.get_next_game_description()),
 44                ],
 45            )
 46            Text(
 47                txt,
 48                maxwidth=900,
 49                h_attach=Text.HAttach.CENTER,
 50                v_attach=Text.VAttach.BOTTOM,
 51                h_align=Text.HAlign.CENTER,
 52                v_align=Text.VAlign.CENTER,
 53                position=(0, 53),
 54                flash=False,
 55                color=(0.3, 0.3, 0.35, 1.0),
 56                transition=Text.Transition.FADE_IN,
 57                transition_delay=2.0,
 58            ).autoretain()
 59
 60    def show_player_scores(
 61        self,
 62        delay: float = 2.5,
 63        results: ba.GameResults | None = None,
 64        scale: float = 1.0,
 65        x_offset: float = 0.0,
 66        y_offset: float = 0.0,
 67    ) -> None:
 68        """Show scores for individual players."""
 69        # pylint: disable=too-many-locals
 70        # pylint: disable=too-many-statements
 71
 72        ts_v_offset = 150.0 + y_offset
 73        ts_h_offs = 80.0 + x_offset
 74        tdelay = delay
 75        spacing = 40
 76
 77        is_free_for_all = isinstance(self.session, ba.FreeForAllSession)
 78
 79        def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None:
 80            if is_free_for_all and results is not None:
 81                assert isinstance(results, ba.GameResults)
 82                assert p_rec.team.activityteam is not None
 83                val = results.get_sessionteam_score(p_rec.team)
 84                return val
 85            return p_rec.accumscore
 86
 87        def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr:
 88            if is_free_for_all and results is not None:
 89                assert isinstance(results, ba.GameResults)
 90                assert p_rec.team.activityteam is not None
 91                val = results.get_sessionteam_score_str(p_rec.team)
 92                assert val is not None
 93                return val
 94            return str(p_rec.accumscore)
 95
 96        # stats.get_records() can return players that are no longer in
 97        # the game.. if we're using results we have to filter those out
 98        # (since they're not in results and that's where we pull their
 99        # scores from)
100        if results is not None:
101            assert isinstance(results, ba.GameResults)
102            player_records = []
103            assert self.stats
104            valid_players = list(self.stats.get_records().items())
105
106            # noinspection PyUnresolvedReferences
107            def _get_player_score_set_entry(
108                player: ba.SessionPlayer,
109            ) -> ba.PlayerRecord | None:
110                for p_rec in valid_players:
111                    if p_rec[1].player is player:
112                        return p_rec[1]
113                return None
114
115            # Results is already sorted; just convert it into a list of
116            # score-set-entries.
117            for winnergroup in results.winnergroups:
118                for team in winnergroup.teams:
119                    if len(team.players) == 1:
120                        player_entry = _get_player_score_set_entry(
121                            team.players[0]
122                        )
123                        if player_entry is not None:
124                            player_records.append(player_entry)
125        else:
126            player_records = []
127            player_records_scores = [
128                (_get_prec_score(p), name, p)
129                for name, p in list(self.stats.get_records().items())
130            ]
131            player_records_scores.sort(reverse=True)
132
133            # Just want living player entries.
134            player_records = [p[2] for p in player_records_scores if p[2]]
135
136        voffs = -140.0 + spacing * len(player_records) * 0.5
137
138        def _txt(
139            xoffs: float,
140            yoffs: float,
141            text: ba.Lstr,
142            h_align: Text.HAlign = Text.HAlign.RIGHT,
143            extrascale: float = 1.0,
144            maxwidth: float | None = 120.0,
145        ) -> None:
146            Text(
147                text,
148                color=(0.5, 0.5, 0.6, 0.5),
149                position=(
150                    ts_h_offs + xoffs * scale,
151                    ts_v_offset + (voffs + yoffs + 4.0) * scale,
152                ),
153                h_align=h_align,
154                v_align=Text.VAlign.CENTER,
155                scale=0.8 * scale * extrascale,
156                maxwidth=maxwidth,
157                transition=Text.Transition.IN_LEFT,
158                transition_delay=tdelay,
159            ).autoretain()
160
161        session = self.session
162        assert isinstance(session, ba.MultiTeamSession)
163        tval = ba.Lstr(
164            resource='gameLeadersText',
165            subs=[('${COUNT}', str(session.get_game_number()))],
166        )
167        _txt(
168            180,
169            43,
170            tval,
171            h_align=Text.HAlign.CENTER,
172            extrascale=1.4,
173            maxwidth=None,
174        )
175        _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT)
176        _txt(180, 4, ba.Lstr(resource='killsText'))
177        _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100)
178
179        score_label = 'Score' if results is None else results.score_label
180        translated = ba.Lstr(translate=('scoreNames', score_label))
181
182        _txt(390, 0, translated)
183
184        topkillcount = 0
185        topkilledcount = 99999
186        top_score = (
187            0 if not player_records else _get_prec_score(player_records[0])
188        )
189
190        for prec in player_records:
191            topkillcount = max(topkillcount, prec.accum_kill_count)
192            topkilledcount = min(topkilledcount, prec.accum_killed_count)
193
194        def _scoretxt(
195            text: str | ba.Lstr,
196            x_offs: float,
197            highlight: bool,
198            delay2: float,
199            maxwidth: float = 70.0,
200        ) -> None:
201            Text(
202                text,
203                position=(
204                    ts_h_offs + x_offs * scale,
205                    ts_v_offset + (voffs + 15) * scale,
206                ),
207                scale=scale,
208                color=(1.0, 0.9, 0.5, 1.0)
209                if highlight
210                else (0.5, 0.5, 0.6, 0.5),
211                h_align=Text.HAlign.RIGHT,
212                v_align=Text.VAlign.CENTER,
213                maxwidth=maxwidth,
214                transition=Text.Transition.IN_LEFT,
215                transition_delay=tdelay + delay2,
216            ).autoretain()
217
218        for playerrec in player_records:
219            tdelay += 0.05
220            voffs -= spacing
221            Image(
222                playerrec.get_icon(),
223                position=(
224                    ts_h_offs - 12 * scale,
225                    ts_v_offset + (voffs + 15.0) * scale,
226                ),
227                scale=(30.0 * scale, 30.0 * scale),
228                transition=Image.Transition.IN_LEFT,
229                transition_delay=tdelay,
230            ).autoretain()
231            Text(
232                ba.Lstr(value=playerrec.getname(full=True)),
233                maxwidth=160,
234                scale=0.75 * scale,
235                position=(
236                    ts_h_offs + 10.0 * scale,
237                    ts_v_offset + (voffs + 15) * scale,
238                ),
239                h_align=Text.HAlign.LEFT,
240                v_align=Text.VAlign.CENTER,
241                color=ba.safecolor(playerrec.team.color + (1,)),
242                transition=Text.Transition.IN_LEFT,
243                transition_delay=tdelay,
244            ).autoretain()
245            _scoretxt(
246                str(playerrec.accum_kill_count),
247                180,
248                playerrec.accum_kill_count == topkillcount,
249                0.1,
250            )
251            _scoretxt(
252                str(playerrec.accum_killed_count),
253                280,
254                playerrec.accum_killed_count == topkilledcount,
255                0.1,
256            )
257            _scoretxt(
258                _get_prec_score_str(playerrec),
259                390,
260                _get_prec_score(playerrec) == top_score,
261                0.2,
262            )
class MultiTeamScoreScreenActivity(ba._activity.Activity[ba._player.EmptyPlayer, ba._team.EmptyTeam]):
 18class MultiTeamScoreScreenActivity(ScoreScreenActivity):
 19    """Base class for score screens."""
 20
 21    def __init__(self, settings: dict):
 22        super().__init__(settings=settings)
 23        self._score_display_sound = ba.getsound('scoreHit01')
 24        self._score_display_sound_small = ba.getsound('scoreHit02')
 25
 26        self._show_up_next: bool = True
 27
 28    def on_begin(self) -> None:
 29        super().on_begin()
 30        session = self.session
 31        if self._show_up_next and isinstance(session, ba.MultiTeamSession):
 32            txt = ba.Lstr(
 33                value='${A}   ${B}',
 34                subs=[
 35                    (
 36                        '${A}',
 37                        ba.Lstr(
 38                            resource='upNextText',
 39                            subs=[
 40                                ('${COUNT}', str(session.get_game_number() + 1))
 41                            ],
 42                        ),
 43                    ),
 44                    ('${B}', session.get_next_game_description()),
 45                ],
 46            )
 47            Text(
 48                txt,
 49                maxwidth=900,
 50                h_attach=Text.HAttach.CENTER,
 51                v_attach=Text.VAttach.BOTTOM,
 52                h_align=Text.HAlign.CENTER,
 53                v_align=Text.VAlign.CENTER,
 54                position=(0, 53),
 55                flash=False,
 56                color=(0.3, 0.3, 0.35, 1.0),
 57                transition=Text.Transition.FADE_IN,
 58                transition_delay=2.0,
 59            ).autoretain()
 60
 61    def show_player_scores(
 62        self,
 63        delay: float = 2.5,
 64        results: ba.GameResults | None = None,
 65        scale: float = 1.0,
 66        x_offset: float = 0.0,
 67        y_offset: float = 0.0,
 68    ) -> None:
 69        """Show scores for individual players."""
 70        # pylint: disable=too-many-locals
 71        # pylint: disable=too-many-statements
 72
 73        ts_v_offset = 150.0 + y_offset
 74        ts_h_offs = 80.0 + x_offset
 75        tdelay = delay
 76        spacing = 40
 77
 78        is_free_for_all = isinstance(self.session, ba.FreeForAllSession)
 79
 80        def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None:
 81            if is_free_for_all and results is not None:
 82                assert isinstance(results, ba.GameResults)
 83                assert p_rec.team.activityteam is not None
 84                val = results.get_sessionteam_score(p_rec.team)
 85                return val
 86            return p_rec.accumscore
 87
 88        def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr:
 89            if is_free_for_all and results is not None:
 90                assert isinstance(results, ba.GameResults)
 91                assert p_rec.team.activityteam is not None
 92                val = results.get_sessionteam_score_str(p_rec.team)
 93                assert val is not None
 94                return val
 95            return str(p_rec.accumscore)
 96
 97        # stats.get_records() can return players that are no longer in
 98        # the game.. if we're using results we have to filter those out
 99        # (since they're not in results and that's where we pull their
100        # scores from)
101        if results is not None:
102            assert isinstance(results, ba.GameResults)
103            player_records = []
104            assert self.stats
105            valid_players = list(self.stats.get_records().items())
106
107            # noinspection PyUnresolvedReferences
108            def _get_player_score_set_entry(
109                player: ba.SessionPlayer,
110            ) -> ba.PlayerRecord | None:
111                for p_rec in valid_players:
112                    if p_rec[1].player is player:
113                        return p_rec[1]
114                return None
115
116            # Results is already sorted; just convert it into a list of
117            # score-set-entries.
118            for winnergroup in results.winnergroups:
119                for team in winnergroup.teams:
120                    if len(team.players) == 1:
121                        player_entry = _get_player_score_set_entry(
122                            team.players[0]
123                        )
124                        if player_entry is not None:
125                            player_records.append(player_entry)
126        else:
127            player_records = []
128            player_records_scores = [
129                (_get_prec_score(p), name, p)
130                for name, p in list(self.stats.get_records().items())
131            ]
132            player_records_scores.sort(reverse=True)
133
134            # Just want living player entries.
135            player_records = [p[2] for p in player_records_scores if p[2]]
136
137        voffs = -140.0 + spacing * len(player_records) * 0.5
138
139        def _txt(
140            xoffs: float,
141            yoffs: float,
142            text: ba.Lstr,
143            h_align: Text.HAlign = Text.HAlign.RIGHT,
144            extrascale: float = 1.0,
145            maxwidth: float | None = 120.0,
146        ) -> None:
147            Text(
148                text,
149                color=(0.5, 0.5, 0.6, 0.5),
150                position=(
151                    ts_h_offs + xoffs * scale,
152                    ts_v_offset + (voffs + yoffs + 4.0) * scale,
153                ),
154                h_align=h_align,
155                v_align=Text.VAlign.CENTER,
156                scale=0.8 * scale * extrascale,
157                maxwidth=maxwidth,
158                transition=Text.Transition.IN_LEFT,
159                transition_delay=tdelay,
160            ).autoretain()
161
162        session = self.session
163        assert isinstance(session, ba.MultiTeamSession)
164        tval = ba.Lstr(
165            resource='gameLeadersText',
166            subs=[('${COUNT}', str(session.get_game_number()))],
167        )
168        _txt(
169            180,
170            43,
171            tval,
172            h_align=Text.HAlign.CENTER,
173            extrascale=1.4,
174            maxwidth=None,
175        )
176        _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT)
177        _txt(180, 4, ba.Lstr(resource='killsText'))
178        _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100)
179
180        score_label = 'Score' if results is None else results.score_label
181        translated = ba.Lstr(translate=('scoreNames', score_label))
182
183        _txt(390, 0, translated)
184
185        topkillcount = 0
186        topkilledcount = 99999
187        top_score = (
188            0 if not player_records else _get_prec_score(player_records[0])
189        )
190
191        for prec in player_records:
192            topkillcount = max(topkillcount, prec.accum_kill_count)
193            topkilledcount = min(topkilledcount, prec.accum_killed_count)
194
195        def _scoretxt(
196            text: str | ba.Lstr,
197            x_offs: float,
198            highlight: bool,
199            delay2: float,
200            maxwidth: float = 70.0,
201        ) -> None:
202            Text(
203                text,
204                position=(
205                    ts_h_offs + x_offs * scale,
206                    ts_v_offset + (voffs + 15) * scale,
207                ),
208                scale=scale,
209                color=(1.0, 0.9, 0.5, 1.0)
210                if highlight
211                else (0.5, 0.5, 0.6, 0.5),
212                h_align=Text.HAlign.RIGHT,
213                v_align=Text.VAlign.CENTER,
214                maxwidth=maxwidth,
215                transition=Text.Transition.IN_LEFT,
216                transition_delay=tdelay + delay2,
217            ).autoretain()
218
219        for playerrec in player_records:
220            tdelay += 0.05
221            voffs -= spacing
222            Image(
223                playerrec.get_icon(),
224                position=(
225                    ts_h_offs - 12 * scale,
226                    ts_v_offset + (voffs + 15.0) * scale,
227                ),
228                scale=(30.0 * scale, 30.0 * scale),
229                transition=Image.Transition.IN_LEFT,
230                transition_delay=tdelay,
231            ).autoretain()
232            Text(
233                ba.Lstr(value=playerrec.getname(full=True)),
234                maxwidth=160,
235                scale=0.75 * scale,
236                position=(
237                    ts_h_offs + 10.0 * scale,
238                    ts_v_offset + (voffs + 15) * scale,
239                ),
240                h_align=Text.HAlign.LEFT,
241                v_align=Text.VAlign.CENTER,
242                color=ba.safecolor(playerrec.team.color + (1,)),
243                transition=Text.Transition.IN_LEFT,
244                transition_delay=tdelay,
245            ).autoretain()
246            _scoretxt(
247                str(playerrec.accum_kill_count),
248                180,
249                playerrec.accum_kill_count == topkillcount,
250                0.1,
251            )
252            _scoretxt(
253                str(playerrec.accum_killed_count),
254                280,
255                playerrec.accum_killed_count == topkilledcount,
256                0.1,
257            )
258            _scoretxt(
259                _get_prec_score_str(playerrec),
260                390,
261                _get_prec_score(playerrec) == top_score,
262                0.2,
263            )

Base class for score screens.

MultiTeamScoreScreenActivity(settings: dict)
21    def __init__(self, settings: dict):
22        super().__init__(settings=settings)
23        self._score_display_sound = ba.getsound('scoreHit01')
24        self._score_display_sound_small = ba.getsound('scoreHit02')
25
26        self._show_up_next: bool = True

Creates an Activity in the current ba.Session.

The activity will not be actually run until ba.Session.setactivity is called. 'settings' should be a dict of key/value pairs specific to the activity.

Activities should preload as much of their media/etc as possible in their constructor, but none of it should actually be used until they are transitioned in.

def on_begin(self) -> None:
28    def on_begin(self) -> None:
29        super().on_begin()
30        session = self.session
31        if self._show_up_next and isinstance(session, ba.MultiTeamSession):
32            txt = ba.Lstr(
33                value='${A}   ${B}',
34                subs=[
35                    (
36                        '${A}',
37                        ba.Lstr(
38                            resource='upNextText',
39                            subs=[
40                                ('${COUNT}', str(session.get_game_number() + 1))
41                            ],
42                        ),
43                    ),
44                    ('${B}', session.get_next_game_description()),
45                ],
46            )
47            Text(
48                txt,
49                maxwidth=900,
50                h_attach=Text.HAttach.CENTER,
51                v_attach=Text.VAttach.BOTTOM,
52                h_align=Text.HAlign.CENTER,
53                v_align=Text.VAlign.CENTER,
54                position=(0, 53),
55                flash=False,
56                color=(0.3, 0.3, 0.35, 1.0),
57                transition=Text.Transition.FADE_IN,
58                transition_delay=2.0,
59            ).autoretain()

Called once the previous ba.Activity has finished transitioning out.

At this point the activity's initial players and teams are filled in and it should begin its actual game logic.

def show_player_scores( self, delay: float = 2.5, results: ba._gameresults.GameResults | None = None, scale: float = 1.0, x_offset: float = 0.0, y_offset: float = 0.0) -> None:
 61    def show_player_scores(
 62        self,
 63        delay: float = 2.5,
 64        results: ba.GameResults | None = None,
 65        scale: float = 1.0,
 66        x_offset: float = 0.0,
 67        y_offset: float = 0.0,
 68    ) -> None:
 69        """Show scores for individual players."""
 70        # pylint: disable=too-many-locals
 71        # pylint: disable=too-many-statements
 72
 73        ts_v_offset = 150.0 + y_offset
 74        ts_h_offs = 80.0 + x_offset
 75        tdelay = delay
 76        spacing = 40
 77
 78        is_free_for_all = isinstance(self.session, ba.FreeForAllSession)
 79
 80        def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None:
 81            if is_free_for_all and results is not None:
 82                assert isinstance(results, ba.GameResults)
 83                assert p_rec.team.activityteam is not None
 84                val = results.get_sessionteam_score(p_rec.team)
 85                return val
 86            return p_rec.accumscore
 87
 88        def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr:
 89            if is_free_for_all and results is not None:
 90                assert isinstance(results, ba.GameResults)
 91                assert p_rec.team.activityteam is not None
 92                val = results.get_sessionteam_score_str(p_rec.team)
 93                assert val is not None
 94                return val
 95            return str(p_rec.accumscore)
 96
 97        # stats.get_records() can return players that are no longer in
 98        # the game.. if we're using results we have to filter those out
 99        # (since they're not in results and that's where we pull their
100        # scores from)
101        if results is not None:
102            assert isinstance(results, ba.GameResults)
103            player_records = []
104            assert self.stats
105            valid_players = list(self.stats.get_records().items())
106
107            # noinspection PyUnresolvedReferences
108            def _get_player_score_set_entry(
109                player: ba.SessionPlayer,
110            ) -> ba.PlayerRecord | None:
111                for p_rec in valid_players:
112                    if p_rec[1].player is player:
113                        return p_rec[1]
114                return None
115
116            # Results is already sorted; just convert it into a list of
117            # score-set-entries.
118            for winnergroup in results.winnergroups:
119                for team in winnergroup.teams:
120                    if len(team.players) == 1:
121                        player_entry = _get_player_score_set_entry(
122                            team.players[0]
123                        )
124                        if player_entry is not None:
125                            player_records.append(player_entry)
126        else:
127            player_records = []
128            player_records_scores = [
129                (_get_prec_score(p), name, p)
130                for name, p in list(self.stats.get_records().items())
131            ]
132            player_records_scores.sort(reverse=True)
133
134            # Just want living player entries.
135            player_records = [p[2] for p in player_records_scores if p[2]]
136
137        voffs = -140.0 + spacing * len(player_records) * 0.5
138
139        def _txt(
140            xoffs: float,
141            yoffs: float,
142            text: ba.Lstr,
143            h_align: Text.HAlign = Text.HAlign.RIGHT,
144            extrascale: float = 1.0,
145            maxwidth: float | None = 120.0,
146        ) -> None:
147            Text(
148                text,
149                color=(0.5, 0.5, 0.6, 0.5),
150                position=(
151                    ts_h_offs + xoffs * scale,
152                    ts_v_offset + (voffs + yoffs + 4.0) * scale,
153                ),
154                h_align=h_align,
155                v_align=Text.VAlign.CENTER,
156                scale=0.8 * scale * extrascale,
157                maxwidth=maxwidth,
158                transition=Text.Transition.IN_LEFT,
159                transition_delay=tdelay,
160            ).autoretain()
161
162        session = self.session
163        assert isinstance(session, ba.MultiTeamSession)
164        tval = ba.Lstr(
165            resource='gameLeadersText',
166            subs=[('${COUNT}', str(session.get_game_number()))],
167        )
168        _txt(
169            180,
170            43,
171            tval,
172            h_align=Text.HAlign.CENTER,
173            extrascale=1.4,
174            maxwidth=None,
175        )
176        _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT)
177        _txt(180, 4, ba.Lstr(resource='killsText'))
178        _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100)
179
180        score_label = 'Score' if results is None else results.score_label
181        translated = ba.Lstr(translate=('scoreNames', score_label))
182
183        _txt(390, 0, translated)
184
185        topkillcount = 0
186        topkilledcount = 99999
187        top_score = (
188            0 if not player_records else _get_prec_score(player_records[0])
189        )
190
191        for prec in player_records:
192            topkillcount = max(topkillcount, prec.accum_kill_count)
193            topkilledcount = min(topkilledcount, prec.accum_killed_count)
194
195        def _scoretxt(
196            text: str | ba.Lstr,
197            x_offs: float,
198            highlight: bool,
199            delay2: float,
200            maxwidth: float = 70.0,
201        ) -> None:
202            Text(
203                text,
204                position=(
205                    ts_h_offs + x_offs * scale,
206                    ts_v_offset + (voffs + 15) * scale,
207                ),
208                scale=scale,
209                color=(1.0, 0.9, 0.5, 1.0)
210                if highlight
211                else (0.5, 0.5, 0.6, 0.5),
212                h_align=Text.HAlign.RIGHT,
213                v_align=Text.VAlign.CENTER,
214                maxwidth=maxwidth,
215                transition=Text.Transition.IN_LEFT,
216                transition_delay=tdelay + delay2,
217            ).autoretain()
218
219        for playerrec in player_records:
220            tdelay += 0.05
221            voffs -= spacing
222            Image(
223                playerrec.get_icon(),
224                position=(
225                    ts_h_offs - 12 * scale,
226                    ts_v_offset + (voffs + 15.0) * scale,
227                ),
228                scale=(30.0 * scale, 30.0 * scale),
229                transition=Image.Transition.IN_LEFT,
230                transition_delay=tdelay,
231            ).autoretain()
232            Text(
233                ba.Lstr(value=playerrec.getname(full=True)),
234                maxwidth=160,
235                scale=0.75 * scale,
236                position=(
237                    ts_h_offs + 10.0 * scale,
238                    ts_v_offset + (voffs + 15) * scale,
239                ),
240                h_align=Text.HAlign.LEFT,
241                v_align=Text.VAlign.CENTER,
242                color=ba.safecolor(playerrec.team.color + (1,)),
243                transition=Text.Transition.IN_LEFT,
244                transition_delay=tdelay,
245            ).autoretain()
246            _scoretxt(
247                str(playerrec.accum_kill_count),
248                180,
249                playerrec.accum_kill_count == topkillcount,
250                0.1,
251            )
252            _scoretxt(
253                str(playerrec.accum_killed_count),
254                280,
255                playerrec.accum_killed_count == topkilledcount,
256                0.1,
257            )
258            _scoretxt(
259                _get_prec_score_str(playerrec),
260                390,
261                _get_prec_score(playerrec) == top_score,
262                0.2,
263            )

Show scores for individual players.

Inherited Members
ba._activitytypes.ScoreScreenActivity
transition_time
inherits_tint
inherits_vr_camera_offset
use_fixed_vr_overlay
default_music
on_player_join
on_transition_in
ba._activity.Activity
settings_raw
teams
players
announce_player_deaths
is_joining_activity
allow_pausing
allow_kick_idle_players
slow_motion
inherits_slow_motion
inherits_music
inherits_vr_overlay_center
allow_mid_activity_joins
can_show_ad_on_death
globalsnode
stats
on_expire
customdata
expired
playertype
teamtype
retain_actor
add_actor_weak_ref
session
on_player_leave
on_team_join
on_team_leave
on_transition_out
handlemessage
has_transitioned_in
has_begun
has_ended
is_transitioning_out
transition_out
end
create_player
create_team
ba._dependency.DependencyComponent
dep_is_present
get_dynamic_deps