bastd.activity.freeforallvictory
Functionality related to the final screen in free-for-all games.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Functionality related to the final screen in free-for-all games.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import ba 10from bastd.activity.multiteamscore import MultiTeamScoreScreenActivity 11 12if TYPE_CHECKING: 13 from typing import Any 14 15 16class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): 17 """Score screen shown at after free-for-all rounds.""" 18 19 def __init__(self, settings: dict): 20 super().__init__(settings=settings) 21 22 # Keep prev activity alive while we fade in. 23 self.transition_time = 0.5 24 self._cymbal_sound = ba.getsound('cymbal') 25 26 def on_begin(self) -> None: 27 # pylint: disable=too-many-locals 28 # pylint: disable=too-many-statements 29 from bastd.actor.text import Text 30 from bastd.actor.image import Image 31 32 ba.set_analytics_screen('FreeForAll Score Screen') 33 super().on_begin() 34 35 y_base = 100.0 36 ts_h_offs = -305.0 37 tdelay = 1.0 38 scale = 1.2 39 spacing = 37.0 40 41 # We include name and previous score in the sort to reduce the amount 42 # of random jumping around the list we do in cases of ties. 43 player_order_prev = list(self.players) 44 player_order_prev.sort( 45 reverse=True, 46 key=lambda p: ( 47 p.team.sessionteam.customdata['previous_score'], 48 p.getname(full=True), 49 ), 50 ) 51 player_order = list(self.players) 52 player_order.sort( 53 reverse=True, 54 key=lambda p: ( 55 p.team.sessionteam.customdata['score'], 56 p.team.sessionteam.customdata['score'], 57 p.getname(full=True), 58 ), 59 ) 60 61 v_offs = -74.0 + spacing * len(player_order_prev) * 0.5 62 delay1 = 1.3 + 0.1 63 delay2 = 2.9 + 0.1 64 delay3 = 2.9 + 0.1 65 order_change = player_order != player_order_prev 66 67 if order_change: 68 delay3 += 1.5 69 70 ba.timer(0.3, ba.Call(ba.playsound, self._score_display_sound)) 71 results = self.settings_raw['results'] 72 assert isinstance(results, ba.GameResults) 73 self.show_player_scores( 74 delay=0.001, results=results, scale=1.2, x_offset=-110.0 75 ) 76 77 sound_times: set[float] = set() 78 79 def _scoretxt( 80 text: str, 81 x_offs: float, 82 y_offs: float, 83 highlight: bool, 84 delay: float, 85 extrascale: float, 86 flash: bool = False, 87 ) -> Text: 88 return Text( 89 text, 90 position=( 91 ts_h_offs + x_offs * scale, 92 y_base + (y_offs + v_offs + 2.0) * scale, 93 ), 94 scale=scale * extrascale, 95 color=( 96 (1.0, 0.7, 0.3, 1.0) if highlight else (0.7, 0.7, 0.7, 0.7) 97 ), 98 h_align=Text.HAlign.RIGHT, 99 transition=Text.Transition.IN_LEFT, 100 transition_delay=tdelay + delay, 101 flash=flash, 102 ).autoretain() 103 104 v_offs -= spacing 105 slide_amt = 0.0 106 transtime = 0.250 107 transtime2 = 0.250 108 109 session = self.session 110 assert isinstance(session, ba.FreeForAllSession) 111 title = Text( 112 ba.Lstr( 113 resource='firstToSeriesText', 114 subs=[('${COUNT}', str(session.get_ffa_series_length()))], 115 ), 116 scale=1.05 * scale, 117 position=( 118 ts_h_offs - 0.0 * scale, 119 y_base + (v_offs + 50.0) * scale, 120 ), 121 h_align=Text.HAlign.CENTER, 122 color=(0.5, 0.5, 0.5, 0.5), 123 transition=Text.Transition.IN_LEFT, 124 transition_delay=tdelay, 125 ).autoretain() 126 127 v_offs -= 25 128 v_offs_start = v_offs 129 130 ba.timer( 131 tdelay + delay3, 132 ba.WeakCall( 133 self._safe_animate, 134 title.position_combine, 135 'input0', 136 { 137 0.0: ts_h_offs - 0.0 * scale, 138 transtime2: ts_h_offs - (0.0 + slide_amt) * scale, 139 }, 140 ), 141 ) 142 143 for i, player in enumerate(player_order_prev): 144 v_offs_2 = v_offs_start - spacing * (player_order.index(player)) 145 ba.timer( 146 tdelay + 0.3, 147 ba.Call(ba.playsound, self._score_display_sound_small), 148 ) 149 if order_change: 150 ba.timer( 151 tdelay + delay2 + 0.1, 152 ba.Call(ba.playsound, self._cymbal_sound), 153 ) 154 img = Image( 155 player.get_icon(), 156 position=( 157 ts_h_offs - 72.0 * scale, 158 y_base + (v_offs + 15.0) * scale, 159 ), 160 scale=(30.0 * scale, 30.0 * scale), 161 transition=Image.Transition.IN_LEFT, 162 transition_delay=tdelay, 163 ).autoretain() 164 ba.timer( 165 tdelay + delay2, 166 ba.WeakCall( 167 self._safe_animate, 168 img.position_combine, 169 'input1', 170 { 171 0: y_base + (v_offs + 15.0) * scale, 172 transtime: y_base + (v_offs_2 + 15.0) * scale, 173 }, 174 ), 175 ) 176 ba.timer( 177 tdelay + delay3, 178 ba.WeakCall( 179 self._safe_animate, 180 img.position_combine, 181 'input0', 182 { 183 0: ts_h_offs - 72.0 * scale, 184 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 185 }, 186 ), 187 ) 188 txt = Text( 189 ba.Lstr(value=player.getname(full=True)), 190 maxwidth=130.0, 191 scale=0.75 * scale, 192 position=( 193 ts_h_offs - 50.0 * scale, 194 y_base + (v_offs + 15.0) * scale, 195 ), 196 h_align=Text.HAlign.LEFT, 197 v_align=Text.VAlign.CENTER, 198 color=ba.safecolor(player.team.color + (1,)), 199 transition=Text.Transition.IN_LEFT, 200 transition_delay=tdelay, 201 ).autoretain() 202 ba.timer( 203 tdelay + delay2, 204 ba.WeakCall( 205 self._safe_animate, 206 txt.position_combine, 207 'input1', 208 { 209 0: y_base + (v_offs + 15.0) * scale, 210 transtime: y_base + (v_offs_2 + 15.0) * scale, 211 }, 212 ), 213 ) 214 ba.timer( 215 tdelay + delay3, 216 ba.WeakCall( 217 self._safe_animate, 218 txt.position_combine, 219 'input0', 220 { 221 0: ts_h_offs - 50.0 * scale, 222 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 223 }, 224 ), 225 ) 226 227 txt_num = Text( 228 '#' + str(i + 1), 229 scale=0.55 * scale, 230 position=( 231 ts_h_offs - 95.0 * scale, 232 y_base + (v_offs + 8.0) * scale, 233 ), 234 h_align=Text.HAlign.RIGHT, 235 color=(0.6, 0.6, 0.6, 0.6), 236 transition=Text.Transition.IN_LEFT, 237 transition_delay=tdelay, 238 ).autoretain() 239 ba.timer( 240 tdelay + delay3, 241 ba.WeakCall( 242 self._safe_animate, 243 txt_num.position_combine, 244 'input0', 245 { 246 0: ts_h_offs - 95.0 * scale, 247 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 248 }, 249 ), 250 ) 251 252 s_txt = _scoretxt( 253 str(player.team.sessionteam.customdata['previous_score']), 254 80, 255 0, 256 False, 257 0, 258 1.0, 259 ) 260 ba.timer( 261 tdelay + delay2, 262 ba.WeakCall( 263 self._safe_animate, 264 s_txt.position_combine, 265 'input1', 266 { 267 0: y_base + (v_offs + 2.0) * scale, 268 transtime: y_base + (v_offs_2 + 2.0) * scale, 269 }, 270 ), 271 ) 272 ba.timer( 273 tdelay + delay3, 274 ba.WeakCall( 275 self._safe_animate, 276 s_txt.position_combine, 277 'input0', 278 { 279 0: ts_h_offs + 80.0 * scale, 280 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 281 }, 282 ), 283 ) 284 285 score_change = ( 286 player.team.sessionteam.customdata['score'] 287 - player.team.sessionteam.customdata['previous_score'] 288 ) 289 if score_change > 0: 290 xval = 113 291 yval = 3.0 292 s_txt_2 = _scoretxt( 293 '+' + str(score_change), 294 xval, 295 yval, 296 True, 297 0, 298 0.7, 299 flash=True, 300 ) 301 ba.timer( 302 tdelay + delay2, 303 ba.WeakCall( 304 self._safe_animate, 305 s_txt_2.position_combine, 306 'input1', 307 { 308 0: y_base + (v_offs + yval + 2.0) * scale, 309 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 310 }, 311 ), 312 ) 313 ba.timer( 314 tdelay + delay3, 315 ba.WeakCall( 316 self._safe_animate, 317 s_txt_2.position_combine, 318 'input0', 319 { 320 0: ts_h_offs + xval * scale, 321 transtime2: ts_h_offs + (xval - slide_amt) * scale, 322 }, 323 ), 324 ) 325 326 def _safesetattr( 327 node: ba.Node | None, attr: str, value: Any 328 ) -> None: 329 if node: 330 setattr(node, attr, value) 331 332 ba.timer( 333 tdelay + delay1, 334 ba.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 335 ) 336 for j in range(score_change): 337 ba.timer( 338 (tdelay + delay1 + 0.15 * j), 339 ba.Call( 340 _safesetattr, 341 s_txt.node, 342 'text', 343 str( 344 player.team.sessionteam.customdata[ 345 'previous_score' 346 ] 347 + j 348 + 1 349 ), 350 ), 351 ) 352 tfin = tdelay + delay1 + 0.15 * j 353 if tfin not in sound_times: 354 sound_times.add(tfin) 355 ba.timer( 356 tfin, 357 ba.Call( 358 ba.playsound, self._score_display_sound_small 359 ), 360 ) 361 v_offs -= spacing 362 363 def _safe_animate( 364 self, node: ba.Node | None, attr: str, keys: dict[float, float] 365 ) -> None: 366 """Run an animation on a node if the node still exists.""" 367 if node: 368 ba.animate(node, attr, keys)
17class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): 18 """Score screen shown at after free-for-all rounds.""" 19 20 def __init__(self, settings: dict): 21 super().__init__(settings=settings) 22 23 # Keep prev activity alive while we fade in. 24 self.transition_time = 0.5 25 self._cymbal_sound = ba.getsound('cymbal') 26 27 def on_begin(self) -> None: 28 # pylint: disable=too-many-locals 29 # pylint: disable=too-many-statements 30 from bastd.actor.text import Text 31 from bastd.actor.image import Image 32 33 ba.set_analytics_screen('FreeForAll Score Screen') 34 super().on_begin() 35 36 y_base = 100.0 37 ts_h_offs = -305.0 38 tdelay = 1.0 39 scale = 1.2 40 spacing = 37.0 41 42 # We include name and previous score in the sort to reduce the amount 43 # of random jumping around the list we do in cases of ties. 44 player_order_prev = list(self.players) 45 player_order_prev.sort( 46 reverse=True, 47 key=lambda p: ( 48 p.team.sessionteam.customdata['previous_score'], 49 p.getname(full=True), 50 ), 51 ) 52 player_order = list(self.players) 53 player_order.sort( 54 reverse=True, 55 key=lambda p: ( 56 p.team.sessionteam.customdata['score'], 57 p.team.sessionteam.customdata['score'], 58 p.getname(full=True), 59 ), 60 ) 61 62 v_offs = -74.0 + spacing * len(player_order_prev) * 0.5 63 delay1 = 1.3 + 0.1 64 delay2 = 2.9 + 0.1 65 delay3 = 2.9 + 0.1 66 order_change = player_order != player_order_prev 67 68 if order_change: 69 delay3 += 1.5 70 71 ba.timer(0.3, ba.Call(ba.playsound, self._score_display_sound)) 72 results = self.settings_raw['results'] 73 assert isinstance(results, ba.GameResults) 74 self.show_player_scores( 75 delay=0.001, results=results, scale=1.2, x_offset=-110.0 76 ) 77 78 sound_times: set[float] = set() 79 80 def _scoretxt( 81 text: str, 82 x_offs: float, 83 y_offs: float, 84 highlight: bool, 85 delay: float, 86 extrascale: float, 87 flash: bool = False, 88 ) -> Text: 89 return Text( 90 text, 91 position=( 92 ts_h_offs + x_offs * scale, 93 y_base + (y_offs + v_offs + 2.0) * scale, 94 ), 95 scale=scale * extrascale, 96 color=( 97 (1.0, 0.7, 0.3, 1.0) if highlight else (0.7, 0.7, 0.7, 0.7) 98 ), 99 h_align=Text.HAlign.RIGHT, 100 transition=Text.Transition.IN_LEFT, 101 transition_delay=tdelay + delay, 102 flash=flash, 103 ).autoretain() 104 105 v_offs -= spacing 106 slide_amt = 0.0 107 transtime = 0.250 108 transtime2 = 0.250 109 110 session = self.session 111 assert isinstance(session, ba.FreeForAllSession) 112 title = Text( 113 ba.Lstr( 114 resource='firstToSeriesText', 115 subs=[('${COUNT}', str(session.get_ffa_series_length()))], 116 ), 117 scale=1.05 * scale, 118 position=( 119 ts_h_offs - 0.0 * scale, 120 y_base + (v_offs + 50.0) * scale, 121 ), 122 h_align=Text.HAlign.CENTER, 123 color=(0.5, 0.5, 0.5, 0.5), 124 transition=Text.Transition.IN_LEFT, 125 transition_delay=tdelay, 126 ).autoretain() 127 128 v_offs -= 25 129 v_offs_start = v_offs 130 131 ba.timer( 132 tdelay + delay3, 133 ba.WeakCall( 134 self._safe_animate, 135 title.position_combine, 136 'input0', 137 { 138 0.0: ts_h_offs - 0.0 * scale, 139 transtime2: ts_h_offs - (0.0 + slide_amt) * scale, 140 }, 141 ), 142 ) 143 144 for i, player in enumerate(player_order_prev): 145 v_offs_2 = v_offs_start - spacing * (player_order.index(player)) 146 ba.timer( 147 tdelay + 0.3, 148 ba.Call(ba.playsound, self._score_display_sound_small), 149 ) 150 if order_change: 151 ba.timer( 152 tdelay + delay2 + 0.1, 153 ba.Call(ba.playsound, self._cymbal_sound), 154 ) 155 img = Image( 156 player.get_icon(), 157 position=( 158 ts_h_offs - 72.0 * scale, 159 y_base + (v_offs + 15.0) * scale, 160 ), 161 scale=(30.0 * scale, 30.0 * scale), 162 transition=Image.Transition.IN_LEFT, 163 transition_delay=tdelay, 164 ).autoretain() 165 ba.timer( 166 tdelay + delay2, 167 ba.WeakCall( 168 self._safe_animate, 169 img.position_combine, 170 'input1', 171 { 172 0: y_base + (v_offs + 15.0) * scale, 173 transtime: y_base + (v_offs_2 + 15.0) * scale, 174 }, 175 ), 176 ) 177 ba.timer( 178 tdelay + delay3, 179 ba.WeakCall( 180 self._safe_animate, 181 img.position_combine, 182 'input0', 183 { 184 0: ts_h_offs - 72.0 * scale, 185 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 186 }, 187 ), 188 ) 189 txt = Text( 190 ba.Lstr(value=player.getname(full=True)), 191 maxwidth=130.0, 192 scale=0.75 * scale, 193 position=( 194 ts_h_offs - 50.0 * scale, 195 y_base + (v_offs + 15.0) * scale, 196 ), 197 h_align=Text.HAlign.LEFT, 198 v_align=Text.VAlign.CENTER, 199 color=ba.safecolor(player.team.color + (1,)), 200 transition=Text.Transition.IN_LEFT, 201 transition_delay=tdelay, 202 ).autoretain() 203 ba.timer( 204 tdelay + delay2, 205 ba.WeakCall( 206 self._safe_animate, 207 txt.position_combine, 208 'input1', 209 { 210 0: y_base + (v_offs + 15.0) * scale, 211 transtime: y_base + (v_offs_2 + 15.0) * scale, 212 }, 213 ), 214 ) 215 ba.timer( 216 tdelay + delay3, 217 ba.WeakCall( 218 self._safe_animate, 219 txt.position_combine, 220 'input0', 221 { 222 0: ts_h_offs - 50.0 * scale, 223 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 224 }, 225 ), 226 ) 227 228 txt_num = Text( 229 '#' + str(i + 1), 230 scale=0.55 * scale, 231 position=( 232 ts_h_offs - 95.0 * scale, 233 y_base + (v_offs + 8.0) * scale, 234 ), 235 h_align=Text.HAlign.RIGHT, 236 color=(0.6, 0.6, 0.6, 0.6), 237 transition=Text.Transition.IN_LEFT, 238 transition_delay=tdelay, 239 ).autoretain() 240 ba.timer( 241 tdelay + delay3, 242 ba.WeakCall( 243 self._safe_animate, 244 txt_num.position_combine, 245 'input0', 246 { 247 0: ts_h_offs - 95.0 * scale, 248 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 249 }, 250 ), 251 ) 252 253 s_txt = _scoretxt( 254 str(player.team.sessionteam.customdata['previous_score']), 255 80, 256 0, 257 False, 258 0, 259 1.0, 260 ) 261 ba.timer( 262 tdelay + delay2, 263 ba.WeakCall( 264 self._safe_animate, 265 s_txt.position_combine, 266 'input1', 267 { 268 0: y_base + (v_offs + 2.0) * scale, 269 transtime: y_base + (v_offs_2 + 2.0) * scale, 270 }, 271 ), 272 ) 273 ba.timer( 274 tdelay + delay3, 275 ba.WeakCall( 276 self._safe_animate, 277 s_txt.position_combine, 278 'input0', 279 { 280 0: ts_h_offs + 80.0 * scale, 281 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 282 }, 283 ), 284 ) 285 286 score_change = ( 287 player.team.sessionteam.customdata['score'] 288 - player.team.sessionteam.customdata['previous_score'] 289 ) 290 if score_change > 0: 291 xval = 113 292 yval = 3.0 293 s_txt_2 = _scoretxt( 294 '+' + str(score_change), 295 xval, 296 yval, 297 True, 298 0, 299 0.7, 300 flash=True, 301 ) 302 ba.timer( 303 tdelay + delay2, 304 ba.WeakCall( 305 self._safe_animate, 306 s_txt_2.position_combine, 307 'input1', 308 { 309 0: y_base + (v_offs + yval + 2.0) * scale, 310 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 311 }, 312 ), 313 ) 314 ba.timer( 315 tdelay + delay3, 316 ba.WeakCall( 317 self._safe_animate, 318 s_txt_2.position_combine, 319 'input0', 320 { 321 0: ts_h_offs + xval * scale, 322 transtime2: ts_h_offs + (xval - slide_amt) * scale, 323 }, 324 ), 325 ) 326 327 def _safesetattr( 328 node: ba.Node | None, attr: str, value: Any 329 ) -> None: 330 if node: 331 setattr(node, attr, value) 332 333 ba.timer( 334 tdelay + delay1, 335 ba.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 336 ) 337 for j in range(score_change): 338 ba.timer( 339 (tdelay + delay1 + 0.15 * j), 340 ba.Call( 341 _safesetattr, 342 s_txt.node, 343 'text', 344 str( 345 player.team.sessionteam.customdata[ 346 'previous_score' 347 ] 348 + j 349 + 1 350 ), 351 ), 352 ) 353 tfin = tdelay + delay1 + 0.15 * j 354 if tfin not in sound_times: 355 sound_times.add(tfin) 356 ba.timer( 357 tfin, 358 ba.Call( 359 ba.playsound, self._score_display_sound_small 360 ), 361 ) 362 v_offs -= spacing 363 364 def _safe_animate( 365 self, node: ba.Node | None, attr: str, keys: dict[float, float] 366 ) -> None: 367 """Run an animation on a node if the node still exists.""" 368 if node: 369 ba.animate(node, attr, keys)
Score screen shown at after free-for-all rounds.
20 def __init__(self, settings: dict): 21 super().__init__(settings=settings) 22 23 # Keep prev activity alive while we fade in. 24 self.transition_time = 0.5 25 self._cymbal_sound = ba.getsound('cymbal')
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.
If the activity fades or transitions in, it should set the length of time here so that previous activities will be kept alive for that long (avoiding 'holes' in the screen) This value is given in real-time seconds.
27 def on_begin(self) -> None: 28 # pylint: disable=too-many-locals 29 # pylint: disable=too-many-statements 30 from bastd.actor.text import Text 31 from bastd.actor.image import Image 32 33 ba.set_analytics_screen('FreeForAll Score Screen') 34 super().on_begin() 35 36 y_base = 100.0 37 ts_h_offs = -305.0 38 tdelay = 1.0 39 scale = 1.2 40 spacing = 37.0 41 42 # We include name and previous score in the sort to reduce the amount 43 # of random jumping around the list we do in cases of ties. 44 player_order_prev = list(self.players) 45 player_order_prev.sort( 46 reverse=True, 47 key=lambda p: ( 48 p.team.sessionteam.customdata['previous_score'], 49 p.getname(full=True), 50 ), 51 ) 52 player_order = list(self.players) 53 player_order.sort( 54 reverse=True, 55 key=lambda p: ( 56 p.team.sessionteam.customdata['score'], 57 p.team.sessionteam.customdata['score'], 58 p.getname(full=True), 59 ), 60 ) 61 62 v_offs = -74.0 + spacing * len(player_order_prev) * 0.5 63 delay1 = 1.3 + 0.1 64 delay2 = 2.9 + 0.1 65 delay3 = 2.9 + 0.1 66 order_change = player_order != player_order_prev 67 68 if order_change: 69 delay3 += 1.5 70 71 ba.timer(0.3, ba.Call(ba.playsound, self._score_display_sound)) 72 results = self.settings_raw['results'] 73 assert isinstance(results, ba.GameResults) 74 self.show_player_scores( 75 delay=0.001, results=results, scale=1.2, x_offset=-110.0 76 ) 77 78 sound_times: set[float] = set() 79 80 def _scoretxt( 81 text: str, 82 x_offs: float, 83 y_offs: float, 84 highlight: bool, 85 delay: float, 86 extrascale: float, 87 flash: bool = False, 88 ) -> Text: 89 return Text( 90 text, 91 position=( 92 ts_h_offs + x_offs * scale, 93 y_base + (y_offs + v_offs + 2.0) * scale, 94 ), 95 scale=scale * extrascale, 96 color=( 97 (1.0, 0.7, 0.3, 1.0) if highlight else (0.7, 0.7, 0.7, 0.7) 98 ), 99 h_align=Text.HAlign.RIGHT, 100 transition=Text.Transition.IN_LEFT, 101 transition_delay=tdelay + delay, 102 flash=flash, 103 ).autoretain() 104 105 v_offs -= spacing 106 slide_amt = 0.0 107 transtime = 0.250 108 transtime2 = 0.250 109 110 session = self.session 111 assert isinstance(session, ba.FreeForAllSession) 112 title = Text( 113 ba.Lstr( 114 resource='firstToSeriesText', 115 subs=[('${COUNT}', str(session.get_ffa_series_length()))], 116 ), 117 scale=1.05 * scale, 118 position=( 119 ts_h_offs - 0.0 * scale, 120 y_base + (v_offs + 50.0) * scale, 121 ), 122 h_align=Text.HAlign.CENTER, 123 color=(0.5, 0.5, 0.5, 0.5), 124 transition=Text.Transition.IN_LEFT, 125 transition_delay=tdelay, 126 ).autoretain() 127 128 v_offs -= 25 129 v_offs_start = v_offs 130 131 ba.timer( 132 tdelay + delay3, 133 ba.WeakCall( 134 self._safe_animate, 135 title.position_combine, 136 'input0', 137 { 138 0.0: ts_h_offs - 0.0 * scale, 139 transtime2: ts_h_offs - (0.0 + slide_amt) * scale, 140 }, 141 ), 142 ) 143 144 for i, player in enumerate(player_order_prev): 145 v_offs_2 = v_offs_start - spacing * (player_order.index(player)) 146 ba.timer( 147 tdelay + 0.3, 148 ba.Call(ba.playsound, self._score_display_sound_small), 149 ) 150 if order_change: 151 ba.timer( 152 tdelay + delay2 + 0.1, 153 ba.Call(ba.playsound, self._cymbal_sound), 154 ) 155 img = Image( 156 player.get_icon(), 157 position=( 158 ts_h_offs - 72.0 * scale, 159 y_base + (v_offs + 15.0) * scale, 160 ), 161 scale=(30.0 * scale, 30.0 * scale), 162 transition=Image.Transition.IN_LEFT, 163 transition_delay=tdelay, 164 ).autoretain() 165 ba.timer( 166 tdelay + delay2, 167 ba.WeakCall( 168 self._safe_animate, 169 img.position_combine, 170 'input1', 171 { 172 0: y_base + (v_offs + 15.0) * scale, 173 transtime: y_base + (v_offs_2 + 15.0) * scale, 174 }, 175 ), 176 ) 177 ba.timer( 178 tdelay + delay3, 179 ba.WeakCall( 180 self._safe_animate, 181 img.position_combine, 182 'input0', 183 { 184 0: ts_h_offs - 72.0 * scale, 185 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 186 }, 187 ), 188 ) 189 txt = Text( 190 ba.Lstr(value=player.getname(full=True)), 191 maxwidth=130.0, 192 scale=0.75 * scale, 193 position=( 194 ts_h_offs - 50.0 * scale, 195 y_base + (v_offs + 15.0) * scale, 196 ), 197 h_align=Text.HAlign.LEFT, 198 v_align=Text.VAlign.CENTER, 199 color=ba.safecolor(player.team.color + (1,)), 200 transition=Text.Transition.IN_LEFT, 201 transition_delay=tdelay, 202 ).autoretain() 203 ba.timer( 204 tdelay + delay2, 205 ba.WeakCall( 206 self._safe_animate, 207 txt.position_combine, 208 'input1', 209 { 210 0: y_base + (v_offs + 15.0) * scale, 211 transtime: y_base + (v_offs_2 + 15.0) * scale, 212 }, 213 ), 214 ) 215 ba.timer( 216 tdelay + delay3, 217 ba.WeakCall( 218 self._safe_animate, 219 txt.position_combine, 220 'input0', 221 { 222 0: ts_h_offs - 50.0 * scale, 223 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 224 }, 225 ), 226 ) 227 228 txt_num = Text( 229 '#' + str(i + 1), 230 scale=0.55 * scale, 231 position=( 232 ts_h_offs - 95.0 * scale, 233 y_base + (v_offs + 8.0) * scale, 234 ), 235 h_align=Text.HAlign.RIGHT, 236 color=(0.6, 0.6, 0.6, 0.6), 237 transition=Text.Transition.IN_LEFT, 238 transition_delay=tdelay, 239 ).autoretain() 240 ba.timer( 241 tdelay + delay3, 242 ba.WeakCall( 243 self._safe_animate, 244 txt_num.position_combine, 245 'input0', 246 { 247 0: ts_h_offs - 95.0 * scale, 248 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 249 }, 250 ), 251 ) 252 253 s_txt = _scoretxt( 254 str(player.team.sessionteam.customdata['previous_score']), 255 80, 256 0, 257 False, 258 0, 259 1.0, 260 ) 261 ba.timer( 262 tdelay + delay2, 263 ba.WeakCall( 264 self._safe_animate, 265 s_txt.position_combine, 266 'input1', 267 { 268 0: y_base + (v_offs + 2.0) * scale, 269 transtime: y_base + (v_offs_2 + 2.0) * scale, 270 }, 271 ), 272 ) 273 ba.timer( 274 tdelay + delay3, 275 ba.WeakCall( 276 self._safe_animate, 277 s_txt.position_combine, 278 'input0', 279 { 280 0: ts_h_offs + 80.0 * scale, 281 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 282 }, 283 ), 284 ) 285 286 score_change = ( 287 player.team.sessionteam.customdata['score'] 288 - player.team.sessionteam.customdata['previous_score'] 289 ) 290 if score_change > 0: 291 xval = 113 292 yval = 3.0 293 s_txt_2 = _scoretxt( 294 '+' + str(score_change), 295 xval, 296 yval, 297 True, 298 0, 299 0.7, 300 flash=True, 301 ) 302 ba.timer( 303 tdelay + delay2, 304 ba.WeakCall( 305 self._safe_animate, 306 s_txt_2.position_combine, 307 'input1', 308 { 309 0: y_base + (v_offs + yval + 2.0) * scale, 310 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 311 }, 312 ), 313 ) 314 ba.timer( 315 tdelay + delay3, 316 ba.WeakCall( 317 self._safe_animate, 318 s_txt_2.position_combine, 319 'input0', 320 { 321 0: ts_h_offs + xval * scale, 322 transtime2: ts_h_offs + (xval - slide_amt) * scale, 323 }, 324 ), 325 ) 326 327 def _safesetattr( 328 node: ba.Node | None, attr: str, value: Any 329 ) -> None: 330 if node: 331 setattr(node, attr, value) 332 333 ba.timer( 334 tdelay + delay1, 335 ba.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 336 ) 337 for j in range(score_change): 338 ba.timer( 339 (tdelay + delay1 + 0.15 * j), 340 ba.Call( 341 _safesetattr, 342 s_txt.node, 343 'text', 344 str( 345 player.team.sessionteam.customdata[ 346 'previous_score' 347 ] 348 + j 349 + 1 350 ), 351 ), 352 ) 353 tfin = tdelay + delay1 + 0.15 * j 354 if tfin not in sound_times: 355 sound_times.add(tfin) 356 ba.timer( 357 tfin, 358 ba.Call( 359 ba.playsound, self._score_display_sound_small 360 ), 361 ) 362 v_offs -= spacing
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.
Inherited Members
- ba._activitytypes.ScoreScreenActivity
- 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