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(value='${A} ${B}', 32 subs=[ 33 ('${A}', 34 ba.Lstr(resource='upNextText', 35 subs=[ 36 ('${COUNT}', 37 str(session.get_game_number() + 1)) 38 ])), 39 ('${B}', session.get_next_game_description()) 40 ]) 41 Text(txt, 42 maxwidth=900, 43 h_attach=Text.HAttach.CENTER, 44 v_attach=Text.VAttach.BOTTOM, 45 h_align=Text.HAlign.CENTER, 46 v_align=Text.VAlign.CENTER, 47 position=(0, 53), 48 flash=False, 49 color=(0.3, 0.3, 0.35, 1.0), 50 transition=Text.Transition.FADE_IN, 51 transition_delay=2.0).autoretain() 52 53 def show_player_scores(self, 54 delay: float = 2.5, 55 results: ba.GameResults | None = None, 56 scale: float = 1.0, 57 x_offset: float = 0.0, 58 y_offset: float = 0.0) -> None: 59 """Show scores for individual players.""" 60 # pylint: disable=too-many-locals 61 # pylint: disable=too-many-statements 62 63 ts_v_offset = 150.0 + y_offset 64 ts_h_offs = 80.0 + x_offset 65 tdelay = delay 66 spacing = 40 67 68 is_free_for_all = isinstance(self.session, ba.FreeForAllSession) 69 70 def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None: 71 if is_free_for_all and results is not None: 72 assert isinstance(results, ba.GameResults) 73 assert p_rec.team.activityteam is not None 74 val = results.get_sessionteam_score(p_rec.team) 75 return val 76 return p_rec.accumscore 77 78 def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr: 79 if is_free_for_all and results is not None: 80 assert isinstance(results, ba.GameResults) 81 assert p_rec.team.activityteam is not None 82 val = results.get_sessionteam_score_str(p_rec.team) 83 assert val is not None 84 return val 85 return str(p_rec.accumscore) 86 87 # stats.get_records() can return players that are no longer in 88 # the game.. if we're using results we have to filter those out 89 # (since they're not in results and that's where we pull their 90 # scores from) 91 if results is not None: 92 assert isinstance(results, ba.GameResults) 93 player_records = [] 94 assert self.stats 95 valid_players = list(self.stats.get_records().items()) 96 97 # noinspection PyUnresolvedReferences 98 def _get_player_score_set_entry( 99 player: ba.SessionPlayer) -> ba.PlayerRecord | None: 100 for p_rec in valid_players: 101 if p_rec[1].player is player: 102 return p_rec[1] 103 return None 104 105 # Results is already sorted; just convert it into a list of 106 # score-set-entries. 107 for winnergroup in results.winnergroups: 108 for team in winnergroup.teams: 109 if len(team.players) == 1: 110 player_entry = _get_player_score_set_entry( 111 team.players[0]) 112 if player_entry is not None: 113 player_records.append(player_entry) 114 else: 115 player_records = [] 116 player_records_scores = [ 117 (_get_prec_score(p), name, p) 118 for name, p in list(self.stats.get_records().items()) 119 ] 120 player_records_scores.sort(reverse=True) 121 122 # Just want living player entries. 123 player_records = [p[2] for p in player_records_scores if p[2]] 124 125 voffs = -140.0 + spacing * len(player_records) * 0.5 126 127 def _txt(xoffs: float, 128 yoffs: float, 129 text: ba.Lstr, 130 h_align: Text.HAlign = Text.HAlign.RIGHT, 131 extrascale: float = 1.0, 132 maxwidth: float | None = 120.0) -> None: 133 Text(text, 134 color=(0.5, 0.5, 0.6, 0.5), 135 position=(ts_h_offs + xoffs * scale, 136 ts_v_offset + (voffs + yoffs + 4.0) * scale), 137 h_align=h_align, 138 v_align=Text.VAlign.CENTER, 139 scale=0.8 * scale * extrascale, 140 maxwidth=maxwidth, 141 transition=Text.Transition.IN_LEFT, 142 transition_delay=tdelay).autoretain() 143 144 session = self.session 145 assert isinstance(session, ba.MultiTeamSession) 146 tval = ba.Lstr(resource='gameLeadersText', 147 subs=[('${COUNT}', str(session.get_game_number()))]) 148 _txt(180, 149 43, 150 tval, 151 h_align=Text.HAlign.CENTER, 152 extrascale=1.4, 153 maxwidth=None) 154 _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT) 155 _txt(180, 4, ba.Lstr(resource='killsText')) 156 _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100) 157 158 score_label = 'Score' if results is None else results.score_label 159 translated = ba.Lstr(translate=('scoreNames', score_label)) 160 161 _txt(390, 0, translated) 162 163 topkillcount = 0 164 topkilledcount = 99999 165 top_score = 0 if not player_records else _get_prec_score( 166 player_records[0]) 167 168 for prec in player_records: 169 topkillcount = max(topkillcount, prec.accum_kill_count) 170 topkilledcount = min(topkilledcount, prec.accum_killed_count) 171 172 def _scoretxt(text: str | ba.Lstr, 173 x_offs: float, 174 highlight: bool, 175 delay2: float, 176 maxwidth: float = 70.0) -> None: 177 Text(text, 178 position=(ts_h_offs + x_offs * scale, 179 ts_v_offset + (voffs + 15) * scale), 180 scale=scale, 181 color=(1.0, 0.9, 0.5, 1.0) if highlight else 182 (0.5, 0.5, 0.6, 0.5), 183 h_align=Text.HAlign.RIGHT, 184 v_align=Text.VAlign.CENTER, 185 maxwidth=maxwidth, 186 transition=Text.Transition.IN_LEFT, 187 transition_delay=tdelay + delay2).autoretain() 188 189 for playerrec in player_records: 190 tdelay += 0.05 191 voffs -= spacing 192 Image(playerrec.get_icon(), 193 position=(ts_h_offs - 12 * scale, 194 ts_v_offset + (voffs + 15.0) * scale), 195 scale=(30.0 * scale, 30.0 * scale), 196 transition=Image.Transition.IN_LEFT, 197 transition_delay=tdelay).autoretain() 198 Text(ba.Lstr(value=playerrec.getname(full=True)), 199 maxwidth=160, 200 scale=0.75 * scale, 201 position=(ts_h_offs + 10.0 * scale, 202 ts_v_offset + (voffs + 15) * scale), 203 h_align=Text.HAlign.LEFT, 204 v_align=Text.VAlign.CENTER, 205 color=ba.safecolor(playerrec.team.color + (1, )), 206 transition=Text.Transition.IN_LEFT, 207 transition_delay=tdelay).autoretain() 208 _scoretxt(str(playerrec.accum_kill_count), 180, 209 playerrec.accum_kill_count == topkillcount, 0.1) 210 _scoretxt(str(playerrec.accum_killed_count), 280, 211 playerrec.accum_killed_count == topkilledcount, 0.1) 212 _scoretxt(_get_prec_score_str(playerrec), 390, 213 _get_prec_score(playerrec) == top_score, 0.2)
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(value='${A} ${B}', 33 subs=[ 34 ('${A}', 35 ba.Lstr(resource='upNextText', 36 subs=[ 37 ('${COUNT}', 38 str(session.get_game_number() + 1)) 39 ])), 40 ('${B}', session.get_next_game_description()) 41 ]) 42 Text(txt, 43 maxwidth=900, 44 h_attach=Text.HAttach.CENTER, 45 v_attach=Text.VAttach.BOTTOM, 46 h_align=Text.HAlign.CENTER, 47 v_align=Text.VAlign.CENTER, 48 position=(0, 53), 49 flash=False, 50 color=(0.3, 0.3, 0.35, 1.0), 51 transition=Text.Transition.FADE_IN, 52 transition_delay=2.0).autoretain() 53 54 def show_player_scores(self, 55 delay: float = 2.5, 56 results: ba.GameResults | None = None, 57 scale: float = 1.0, 58 x_offset: float = 0.0, 59 y_offset: float = 0.0) -> None: 60 """Show scores for individual players.""" 61 # pylint: disable=too-many-locals 62 # pylint: disable=too-many-statements 63 64 ts_v_offset = 150.0 + y_offset 65 ts_h_offs = 80.0 + x_offset 66 tdelay = delay 67 spacing = 40 68 69 is_free_for_all = isinstance(self.session, ba.FreeForAllSession) 70 71 def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None: 72 if is_free_for_all and results is not None: 73 assert isinstance(results, ba.GameResults) 74 assert p_rec.team.activityteam is not None 75 val = results.get_sessionteam_score(p_rec.team) 76 return val 77 return p_rec.accumscore 78 79 def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr: 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_str(p_rec.team) 84 assert val is not None 85 return val 86 return str(p_rec.accumscore) 87 88 # stats.get_records() can return players that are no longer in 89 # the game.. if we're using results we have to filter those out 90 # (since they're not in results and that's where we pull their 91 # scores from) 92 if results is not None: 93 assert isinstance(results, ba.GameResults) 94 player_records = [] 95 assert self.stats 96 valid_players = list(self.stats.get_records().items()) 97 98 # noinspection PyUnresolvedReferences 99 def _get_player_score_set_entry( 100 player: ba.SessionPlayer) -> ba.PlayerRecord | None: 101 for p_rec in valid_players: 102 if p_rec[1].player is player: 103 return p_rec[1] 104 return None 105 106 # Results is already sorted; just convert it into a list of 107 # score-set-entries. 108 for winnergroup in results.winnergroups: 109 for team in winnergroup.teams: 110 if len(team.players) == 1: 111 player_entry = _get_player_score_set_entry( 112 team.players[0]) 113 if player_entry is not None: 114 player_records.append(player_entry) 115 else: 116 player_records = [] 117 player_records_scores = [ 118 (_get_prec_score(p), name, p) 119 for name, p in list(self.stats.get_records().items()) 120 ] 121 player_records_scores.sort(reverse=True) 122 123 # Just want living player entries. 124 player_records = [p[2] for p in player_records_scores if p[2]] 125 126 voffs = -140.0 + spacing * len(player_records) * 0.5 127 128 def _txt(xoffs: float, 129 yoffs: float, 130 text: ba.Lstr, 131 h_align: Text.HAlign = Text.HAlign.RIGHT, 132 extrascale: float = 1.0, 133 maxwidth: float | None = 120.0) -> None: 134 Text(text, 135 color=(0.5, 0.5, 0.6, 0.5), 136 position=(ts_h_offs + xoffs * scale, 137 ts_v_offset + (voffs + yoffs + 4.0) * scale), 138 h_align=h_align, 139 v_align=Text.VAlign.CENTER, 140 scale=0.8 * scale * extrascale, 141 maxwidth=maxwidth, 142 transition=Text.Transition.IN_LEFT, 143 transition_delay=tdelay).autoretain() 144 145 session = self.session 146 assert isinstance(session, ba.MultiTeamSession) 147 tval = ba.Lstr(resource='gameLeadersText', 148 subs=[('${COUNT}', str(session.get_game_number()))]) 149 _txt(180, 150 43, 151 tval, 152 h_align=Text.HAlign.CENTER, 153 extrascale=1.4, 154 maxwidth=None) 155 _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT) 156 _txt(180, 4, ba.Lstr(resource='killsText')) 157 _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100) 158 159 score_label = 'Score' if results is None else results.score_label 160 translated = ba.Lstr(translate=('scoreNames', score_label)) 161 162 _txt(390, 0, translated) 163 164 topkillcount = 0 165 topkilledcount = 99999 166 top_score = 0 if not player_records else _get_prec_score( 167 player_records[0]) 168 169 for prec in player_records: 170 topkillcount = max(topkillcount, prec.accum_kill_count) 171 topkilledcount = min(topkilledcount, prec.accum_killed_count) 172 173 def _scoretxt(text: str | ba.Lstr, 174 x_offs: float, 175 highlight: bool, 176 delay2: float, 177 maxwidth: float = 70.0) -> None: 178 Text(text, 179 position=(ts_h_offs + x_offs * scale, 180 ts_v_offset + (voffs + 15) * scale), 181 scale=scale, 182 color=(1.0, 0.9, 0.5, 1.0) if highlight else 183 (0.5, 0.5, 0.6, 0.5), 184 h_align=Text.HAlign.RIGHT, 185 v_align=Text.VAlign.CENTER, 186 maxwidth=maxwidth, 187 transition=Text.Transition.IN_LEFT, 188 transition_delay=tdelay + delay2).autoretain() 189 190 for playerrec in player_records: 191 tdelay += 0.05 192 voffs -= spacing 193 Image(playerrec.get_icon(), 194 position=(ts_h_offs - 12 * scale, 195 ts_v_offset + (voffs + 15.0) * scale), 196 scale=(30.0 * scale, 30.0 * scale), 197 transition=Image.Transition.IN_LEFT, 198 transition_delay=tdelay).autoretain() 199 Text(ba.Lstr(value=playerrec.getname(full=True)), 200 maxwidth=160, 201 scale=0.75 * scale, 202 position=(ts_h_offs + 10.0 * scale, 203 ts_v_offset + (voffs + 15) * scale), 204 h_align=Text.HAlign.LEFT, 205 v_align=Text.VAlign.CENTER, 206 color=ba.safecolor(playerrec.team.color + (1, )), 207 transition=Text.Transition.IN_LEFT, 208 transition_delay=tdelay).autoretain() 209 _scoretxt(str(playerrec.accum_kill_count), 180, 210 playerrec.accum_kill_count == topkillcount, 0.1) 211 _scoretxt(str(playerrec.accum_killed_count), 280, 212 playerrec.accum_killed_count == topkilledcount, 0.1) 213 _scoretxt(_get_prec_score_str(playerrec), 390, 214 _get_prec_score(playerrec) == top_score, 0.2)
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(value='${A} ${B}', 33 subs=[ 34 ('${A}', 35 ba.Lstr(resource='upNextText', 36 subs=[ 37 ('${COUNT}', 38 str(session.get_game_number() + 1)) 39 ])), 40 ('${B}', session.get_next_game_description()) 41 ]) 42 Text(txt, 43 maxwidth=900, 44 h_attach=Text.HAttach.CENTER, 45 v_attach=Text.VAttach.BOTTOM, 46 h_align=Text.HAlign.CENTER, 47 v_align=Text.VAlign.CENTER, 48 position=(0, 53), 49 flash=False, 50 color=(0.3, 0.3, 0.35, 1.0), 51 transition=Text.Transition.FADE_IN, 52 transition_delay=2.0).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:
54 def show_player_scores(self, 55 delay: float = 2.5, 56 results: ba.GameResults | None = None, 57 scale: float = 1.0, 58 x_offset: float = 0.0, 59 y_offset: float = 0.0) -> None: 60 """Show scores for individual players.""" 61 # pylint: disable=too-many-locals 62 # pylint: disable=too-many-statements 63 64 ts_v_offset = 150.0 + y_offset 65 ts_h_offs = 80.0 + x_offset 66 tdelay = delay 67 spacing = 40 68 69 is_free_for_all = isinstance(self.session, ba.FreeForAllSession) 70 71 def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None: 72 if is_free_for_all and results is not None: 73 assert isinstance(results, ba.GameResults) 74 assert p_rec.team.activityteam is not None 75 val = results.get_sessionteam_score(p_rec.team) 76 return val 77 return p_rec.accumscore 78 79 def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr: 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_str(p_rec.team) 84 assert val is not None 85 return val 86 return str(p_rec.accumscore) 87 88 # stats.get_records() can return players that are no longer in 89 # the game.. if we're using results we have to filter those out 90 # (since they're not in results and that's where we pull their 91 # scores from) 92 if results is not None: 93 assert isinstance(results, ba.GameResults) 94 player_records = [] 95 assert self.stats 96 valid_players = list(self.stats.get_records().items()) 97 98 # noinspection PyUnresolvedReferences 99 def _get_player_score_set_entry( 100 player: ba.SessionPlayer) -> ba.PlayerRecord | None: 101 for p_rec in valid_players: 102 if p_rec[1].player is player: 103 return p_rec[1] 104 return None 105 106 # Results is already sorted; just convert it into a list of 107 # score-set-entries. 108 for winnergroup in results.winnergroups: 109 for team in winnergroup.teams: 110 if len(team.players) == 1: 111 player_entry = _get_player_score_set_entry( 112 team.players[0]) 113 if player_entry is not None: 114 player_records.append(player_entry) 115 else: 116 player_records = [] 117 player_records_scores = [ 118 (_get_prec_score(p), name, p) 119 for name, p in list(self.stats.get_records().items()) 120 ] 121 player_records_scores.sort(reverse=True) 122 123 # Just want living player entries. 124 player_records = [p[2] for p in player_records_scores if p[2]] 125 126 voffs = -140.0 + spacing * len(player_records) * 0.5 127 128 def _txt(xoffs: float, 129 yoffs: float, 130 text: ba.Lstr, 131 h_align: Text.HAlign = Text.HAlign.RIGHT, 132 extrascale: float = 1.0, 133 maxwidth: float | None = 120.0) -> None: 134 Text(text, 135 color=(0.5, 0.5, 0.6, 0.5), 136 position=(ts_h_offs + xoffs * scale, 137 ts_v_offset + (voffs + yoffs + 4.0) * scale), 138 h_align=h_align, 139 v_align=Text.VAlign.CENTER, 140 scale=0.8 * scale * extrascale, 141 maxwidth=maxwidth, 142 transition=Text.Transition.IN_LEFT, 143 transition_delay=tdelay).autoretain() 144 145 session = self.session 146 assert isinstance(session, ba.MultiTeamSession) 147 tval = ba.Lstr(resource='gameLeadersText', 148 subs=[('${COUNT}', str(session.get_game_number()))]) 149 _txt(180, 150 43, 151 tval, 152 h_align=Text.HAlign.CENTER, 153 extrascale=1.4, 154 maxwidth=None) 155 _txt(-15, 4, ba.Lstr(resource='playerText'), h_align=Text.HAlign.LEFT) 156 _txt(180, 4, ba.Lstr(resource='killsText')) 157 _txt(280, 4, ba.Lstr(resource='deathsText'), maxwidth=100) 158 159 score_label = 'Score' if results is None else results.score_label 160 translated = ba.Lstr(translate=('scoreNames', score_label)) 161 162 _txt(390, 0, translated) 163 164 topkillcount = 0 165 topkilledcount = 99999 166 top_score = 0 if not player_records else _get_prec_score( 167 player_records[0]) 168 169 for prec in player_records: 170 topkillcount = max(topkillcount, prec.accum_kill_count) 171 topkilledcount = min(topkilledcount, prec.accum_killed_count) 172 173 def _scoretxt(text: str | ba.Lstr, 174 x_offs: float, 175 highlight: bool, 176 delay2: float, 177 maxwidth: float = 70.0) -> None: 178 Text(text, 179 position=(ts_h_offs + x_offs * scale, 180 ts_v_offset + (voffs + 15) * scale), 181 scale=scale, 182 color=(1.0, 0.9, 0.5, 1.0) if highlight else 183 (0.5, 0.5, 0.6, 0.5), 184 h_align=Text.HAlign.RIGHT, 185 v_align=Text.VAlign.CENTER, 186 maxwidth=maxwidth, 187 transition=Text.Transition.IN_LEFT, 188 transition_delay=tdelay + delay2).autoretain() 189 190 for playerrec in player_records: 191 tdelay += 0.05 192 voffs -= spacing 193 Image(playerrec.get_icon(), 194 position=(ts_h_offs - 12 * scale, 195 ts_v_offset + (voffs + 15.0) * scale), 196 scale=(30.0 * scale, 30.0 * scale), 197 transition=Image.Transition.IN_LEFT, 198 transition_delay=tdelay).autoretain() 199 Text(ba.Lstr(value=playerrec.getname(full=True)), 200 maxwidth=160, 201 scale=0.75 * scale, 202 position=(ts_h_offs + 10.0 * scale, 203 ts_v_offset + (voffs + 15) * scale), 204 h_align=Text.HAlign.LEFT, 205 v_align=Text.VAlign.CENTER, 206 color=ba.safecolor(playerrec.team.color + (1, )), 207 transition=Text.Transition.IN_LEFT, 208 transition_delay=tdelay).autoretain() 209 _scoretxt(str(playerrec.accum_kill_count), 180, 210 playerrec.accum_kill_count == topkillcount, 0.1) 211 _scoretxt(str(playerrec.accum_killed_count), 280, 212 playerrec.accum_killed_count == topkilledcount, 0.1) 213 _scoretxt(_get_prec_score_str(playerrec), 390, 214 _get_prec_score(playerrec) == top_score, 0.2)
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