bascenev1lib.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 9from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity 10import bascenev1 as bs 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 = bs.getsound('cymbal') 25 26 def on_begin(self) -> None: 27 # pylint: disable=too-many-locals 28 # pylint: disable=too-many-statements 29 from bascenev1lib.actor.text import Text 30 from bascenev1lib.actor.image import Image 31 32 bs.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 bs.timer(0.3, self._score_display_sound.play) 71 results = self.settings_raw['results'] 72 assert isinstance(results, bs.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, bs.FreeForAllSession) 111 title = Text( 112 bs.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 bs.timer( 131 tdelay + delay3, 132 bs.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 bs.timer(tdelay + 0.3, self._score_display_sound_small.play) 146 if order_change: 147 bs.timer(tdelay + delay2 + 0.1, self._cymbal_sound.play) 148 img = Image( 149 player.get_icon(), 150 position=( 151 ts_h_offs - 72.0 * scale, 152 y_base + (v_offs + 15.0) * scale, 153 ), 154 scale=(30.0 * scale, 30.0 * scale), 155 transition=Image.Transition.IN_LEFT, 156 transition_delay=tdelay, 157 ).autoretain() 158 bs.timer( 159 tdelay + delay2, 160 bs.WeakCall( 161 self._safe_animate, 162 img.position_combine, 163 'input1', 164 { 165 0: y_base + (v_offs + 15.0) * scale, 166 transtime: y_base + (v_offs_2 + 15.0) * scale, 167 }, 168 ), 169 ) 170 bs.timer( 171 tdelay + delay3, 172 bs.WeakCall( 173 self._safe_animate, 174 img.position_combine, 175 'input0', 176 { 177 0: ts_h_offs - 72.0 * scale, 178 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 179 }, 180 ), 181 ) 182 txt = Text( 183 bs.Lstr(value=player.getname(full=True)), 184 maxwidth=130.0, 185 scale=0.75 * scale, 186 position=( 187 ts_h_offs - 50.0 * scale, 188 y_base + (v_offs + 15.0) * scale, 189 ), 190 h_align=Text.HAlign.LEFT, 191 v_align=Text.VAlign.CENTER, 192 color=bs.safecolor(player.team.color + (1,)), 193 transition=Text.Transition.IN_LEFT, 194 transition_delay=tdelay, 195 ).autoretain() 196 bs.timer( 197 tdelay + delay2, 198 bs.WeakCall( 199 self._safe_animate, 200 txt.position_combine, 201 'input1', 202 { 203 0: y_base + (v_offs + 15.0) * scale, 204 transtime: y_base + (v_offs_2 + 15.0) * scale, 205 }, 206 ), 207 ) 208 bs.timer( 209 tdelay + delay3, 210 bs.WeakCall( 211 self._safe_animate, 212 txt.position_combine, 213 'input0', 214 { 215 0: ts_h_offs - 50.0 * scale, 216 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 217 }, 218 ), 219 ) 220 221 txt_num = Text( 222 '#' + str(i + 1), 223 scale=0.55 * scale, 224 position=( 225 ts_h_offs - 95.0 * scale, 226 y_base + (v_offs + 8.0) * scale, 227 ), 228 h_align=Text.HAlign.RIGHT, 229 color=(0.6, 0.6, 0.6, 0.6), 230 transition=Text.Transition.IN_LEFT, 231 transition_delay=tdelay, 232 ).autoretain() 233 bs.timer( 234 tdelay + delay3, 235 bs.WeakCall( 236 self._safe_animate, 237 txt_num.position_combine, 238 'input0', 239 { 240 0: ts_h_offs - 95.0 * scale, 241 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 242 }, 243 ), 244 ) 245 246 s_txt = _scoretxt( 247 str(player.team.sessionteam.customdata['previous_score']), 248 80, 249 0, 250 False, 251 0, 252 1.0, 253 ) 254 bs.timer( 255 tdelay + delay2, 256 bs.WeakCall( 257 self._safe_animate, 258 s_txt.position_combine, 259 'input1', 260 { 261 0: y_base + (v_offs + 2.0) * scale, 262 transtime: y_base + (v_offs_2 + 2.0) * scale, 263 }, 264 ), 265 ) 266 bs.timer( 267 tdelay + delay3, 268 bs.WeakCall( 269 self._safe_animate, 270 s_txt.position_combine, 271 'input0', 272 { 273 0: ts_h_offs + 80.0 * scale, 274 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 275 }, 276 ), 277 ) 278 279 score_change = ( 280 player.team.sessionteam.customdata['score'] 281 - player.team.sessionteam.customdata['previous_score'] 282 ) 283 if score_change > 0: 284 xval = 113 285 yval = 3.0 286 s_txt_2 = _scoretxt( 287 '+' + str(score_change), 288 xval, 289 yval, 290 True, 291 0, 292 0.7, 293 flash=True, 294 ) 295 bs.timer( 296 tdelay + delay2, 297 bs.WeakCall( 298 self._safe_animate, 299 s_txt_2.position_combine, 300 'input1', 301 { 302 0: y_base + (v_offs + yval + 2.0) * scale, 303 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 304 }, 305 ), 306 ) 307 bs.timer( 308 tdelay + delay3, 309 bs.WeakCall( 310 self._safe_animate, 311 s_txt_2.position_combine, 312 'input0', 313 { 314 0: ts_h_offs + xval * scale, 315 transtime2: ts_h_offs + (xval - slide_amt) * scale, 316 }, 317 ), 318 ) 319 320 def _safesetattr( 321 node: bs.Node | None, attr: str, value: Any 322 ) -> None: 323 if node: 324 setattr(node, attr, value) 325 326 bs.timer( 327 tdelay + delay1, 328 bs.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 329 ) 330 for j in range(score_change): 331 bs.timer( 332 (tdelay + delay1 + 0.15 * j), 333 bs.Call( 334 _safesetattr, 335 s_txt.node, 336 'text', 337 str( 338 player.team.sessionteam.customdata[ 339 'previous_score' 340 ] 341 + j 342 + 1 343 ), 344 ), 345 ) 346 tfin = tdelay + delay1 + 0.15 * j 347 if tfin not in sound_times: 348 sound_times.add(tfin) 349 bs.timer(tfin, self._score_display_sound_small.play) 350 v_offs -= spacing 351 352 def _safe_animate( 353 self, node: bs.Node | None, attr: str, keys: dict[float, float] 354 ) -> None: 355 """Run an animation on a node if the node still exists.""" 356 if node: 357 bs.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 = bs.getsound('cymbal') 26 27 def on_begin(self) -> None: 28 # pylint: disable=too-many-locals 29 # pylint: disable=too-many-statements 30 from bascenev1lib.actor.text import Text 31 from bascenev1lib.actor.image import Image 32 33 bs.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 bs.timer(0.3, self._score_display_sound.play) 72 results = self.settings_raw['results'] 73 assert isinstance(results, bs.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, bs.FreeForAllSession) 112 title = Text( 113 bs.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 bs.timer( 132 tdelay + delay3, 133 bs.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 bs.timer(tdelay + 0.3, self._score_display_sound_small.play) 147 if order_change: 148 bs.timer(tdelay + delay2 + 0.1, self._cymbal_sound.play) 149 img = Image( 150 player.get_icon(), 151 position=( 152 ts_h_offs - 72.0 * scale, 153 y_base + (v_offs + 15.0) * scale, 154 ), 155 scale=(30.0 * scale, 30.0 * scale), 156 transition=Image.Transition.IN_LEFT, 157 transition_delay=tdelay, 158 ).autoretain() 159 bs.timer( 160 tdelay + delay2, 161 bs.WeakCall( 162 self._safe_animate, 163 img.position_combine, 164 'input1', 165 { 166 0: y_base + (v_offs + 15.0) * scale, 167 transtime: y_base + (v_offs_2 + 15.0) * scale, 168 }, 169 ), 170 ) 171 bs.timer( 172 tdelay + delay3, 173 bs.WeakCall( 174 self._safe_animate, 175 img.position_combine, 176 'input0', 177 { 178 0: ts_h_offs - 72.0 * scale, 179 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 180 }, 181 ), 182 ) 183 txt = Text( 184 bs.Lstr(value=player.getname(full=True)), 185 maxwidth=130.0, 186 scale=0.75 * scale, 187 position=( 188 ts_h_offs - 50.0 * scale, 189 y_base + (v_offs + 15.0) * scale, 190 ), 191 h_align=Text.HAlign.LEFT, 192 v_align=Text.VAlign.CENTER, 193 color=bs.safecolor(player.team.color + (1,)), 194 transition=Text.Transition.IN_LEFT, 195 transition_delay=tdelay, 196 ).autoretain() 197 bs.timer( 198 tdelay + delay2, 199 bs.WeakCall( 200 self._safe_animate, 201 txt.position_combine, 202 'input1', 203 { 204 0: y_base + (v_offs + 15.0) * scale, 205 transtime: y_base + (v_offs_2 + 15.0) * scale, 206 }, 207 ), 208 ) 209 bs.timer( 210 tdelay + delay3, 211 bs.WeakCall( 212 self._safe_animate, 213 txt.position_combine, 214 'input0', 215 { 216 0: ts_h_offs - 50.0 * scale, 217 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 218 }, 219 ), 220 ) 221 222 txt_num = Text( 223 '#' + str(i + 1), 224 scale=0.55 * scale, 225 position=( 226 ts_h_offs - 95.0 * scale, 227 y_base + (v_offs + 8.0) * scale, 228 ), 229 h_align=Text.HAlign.RIGHT, 230 color=(0.6, 0.6, 0.6, 0.6), 231 transition=Text.Transition.IN_LEFT, 232 transition_delay=tdelay, 233 ).autoretain() 234 bs.timer( 235 tdelay + delay3, 236 bs.WeakCall( 237 self._safe_animate, 238 txt_num.position_combine, 239 'input0', 240 { 241 0: ts_h_offs - 95.0 * scale, 242 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 243 }, 244 ), 245 ) 246 247 s_txt = _scoretxt( 248 str(player.team.sessionteam.customdata['previous_score']), 249 80, 250 0, 251 False, 252 0, 253 1.0, 254 ) 255 bs.timer( 256 tdelay + delay2, 257 bs.WeakCall( 258 self._safe_animate, 259 s_txt.position_combine, 260 'input1', 261 { 262 0: y_base + (v_offs + 2.0) * scale, 263 transtime: y_base + (v_offs_2 + 2.0) * scale, 264 }, 265 ), 266 ) 267 bs.timer( 268 tdelay + delay3, 269 bs.WeakCall( 270 self._safe_animate, 271 s_txt.position_combine, 272 'input0', 273 { 274 0: ts_h_offs + 80.0 * scale, 275 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 276 }, 277 ), 278 ) 279 280 score_change = ( 281 player.team.sessionteam.customdata['score'] 282 - player.team.sessionteam.customdata['previous_score'] 283 ) 284 if score_change > 0: 285 xval = 113 286 yval = 3.0 287 s_txt_2 = _scoretxt( 288 '+' + str(score_change), 289 xval, 290 yval, 291 True, 292 0, 293 0.7, 294 flash=True, 295 ) 296 bs.timer( 297 tdelay + delay2, 298 bs.WeakCall( 299 self._safe_animate, 300 s_txt_2.position_combine, 301 'input1', 302 { 303 0: y_base + (v_offs + yval + 2.0) * scale, 304 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 305 }, 306 ), 307 ) 308 bs.timer( 309 tdelay + delay3, 310 bs.WeakCall( 311 self._safe_animate, 312 s_txt_2.position_combine, 313 'input0', 314 { 315 0: ts_h_offs + xval * scale, 316 transtime2: ts_h_offs + (xval - slide_amt) * scale, 317 }, 318 ), 319 ) 320 321 def _safesetattr( 322 node: bs.Node | None, attr: str, value: Any 323 ) -> None: 324 if node: 325 setattr(node, attr, value) 326 327 bs.timer( 328 tdelay + delay1, 329 bs.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 330 ) 331 for j in range(score_change): 332 bs.timer( 333 (tdelay + delay1 + 0.15 * j), 334 bs.Call( 335 _safesetattr, 336 s_txt.node, 337 'text', 338 str( 339 player.team.sessionteam.customdata[ 340 'previous_score' 341 ] 342 + j 343 + 1 344 ), 345 ), 346 ) 347 tfin = tdelay + delay1 + 0.15 * j 348 if tfin not in sound_times: 349 sound_times.add(tfin) 350 bs.timer(tfin, self._score_display_sound_small.play) 351 v_offs -= spacing 352 353 def _safe_animate( 354 self, node: bs.Node | None, attr: str, keys: dict[float, float] 355 ) -> None: 356 """Run an animation on a node if the node still exists.""" 357 if node: 358 bs.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 = bs.getsound('cymbal')
Creates an Activity in the current bascenev1.Session.
The activity will not be actually run until bascenev1.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 bascenev1lib.actor.text import Text 31 from bascenev1lib.actor.image import Image 32 33 bs.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 bs.timer(0.3, self._score_display_sound.play) 72 results = self.settings_raw['results'] 73 assert isinstance(results, bs.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, bs.FreeForAllSession) 112 title = Text( 113 bs.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 bs.timer( 132 tdelay + delay3, 133 bs.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 bs.timer(tdelay + 0.3, self._score_display_sound_small.play) 147 if order_change: 148 bs.timer(tdelay + delay2 + 0.1, self._cymbal_sound.play) 149 img = Image( 150 player.get_icon(), 151 position=( 152 ts_h_offs - 72.0 * scale, 153 y_base + (v_offs + 15.0) * scale, 154 ), 155 scale=(30.0 * scale, 30.0 * scale), 156 transition=Image.Transition.IN_LEFT, 157 transition_delay=tdelay, 158 ).autoretain() 159 bs.timer( 160 tdelay + delay2, 161 bs.WeakCall( 162 self._safe_animate, 163 img.position_combine, 164 'input1', 165 { 166 0: y_base + (v_offs + 15.0) * scale, 167 transtime: y_base + (v_offs_2 + 15.0) * scale, 168 }, 169 ), 170 ) 171 bs.timer( 172 tdelay + delay3, 173 bs.WeakCall( 174 self._safe_animate, 175 img.position_combine, 176 'input0', 177 { 178 0: ts_h_offs - 72.0 * scale, 179 transtime2: ts_h_offs - (72.0 + slide_amt) * scale, 180 }, 181 ), 182 ) 183 txt = Text( 184 bs.Lstr(value=player.getname(full=True)), 185 maxwidth=130.0, 186 scale=0.75 * scale, 187 position=( 188 ts_h_offs - 50.0 * scale, 189 y_base + (v_offs + 15.0) * scale, 190 ), 191 h_align=Text.HAlign.LEFT, 192 v_align=Text.VAlign.CENTER, 193 color=bs.safecolor(player.team.color + (1,)), 194 transition=Text.Transition.IN_LEFT, 195 transition_delay=tdelay, 196 ).autoretain() 197 bs.timer( 198 tdelay + delay2, 199 bs.WeakCall( 200 self._safe_animate, 201 txt.position_combine, 202 'input1', 203 { 204 0: y_base + (v_offs + 15.0) * scale, 205 transtime: y_base + (v_offs_2 + 15.0) * scale, 206 }, 207 ), 208 ) 209 bs.timer( 210 tdelay + delay3, 211 bs.WeakCall( 212 self._safe_animate, 213 txt.position_combine, 214 'input0', 215 { 216 0: ts_h_offs - 50.0 * scale, 217 transtime2: ts_h_offs - (50.0 + slide_amt) * scale, 218 }, 219 ), 220 ) 221 222 txt_num = Text( 223 '#' + str(i + 1), 224 scale=0.55 * scale, 225 position=( 226 ts_h_offs - 95.0 * scale, 227 y_base + (v_offs + 8.0) * scale, 228 ), 229 h_align=Text.HAlign.RIGHT, 230 color=(0.6, 0.6, 0.6, 0.6), 231 transition=Text.Transition.IN_LEFT, 232 transition_delay=tdelay, 233 ).autoretain() 234 bs.timer( 235 tdelay + delay3, 236 bs.WeakCall( 237 self._safe_animate, 238 txt_num.position_combine, 239 'input0', 240 { 241 0: ts_h_offs - 95.0 * scale, 242 transtime2: ts_h_offs - (95.0 + slide_amt) * scale, 243 }, 244 ), 245 ) 246 247 s_txt = _scoretxt( 248 str(player.team.sessionteam.customdata['previous_score']), 249 80, 250 0, 251 False, 252 0, 253 1.0, 254 ) 255 bs.timer( 256 tdelay + delay2, 257 bs.WeakCall( 258 self._safe_animate, 259 s_txt.position_combine, 260 'input1', 261 { 262 0: y_base + (v_offs + 2.0) * scale, 263 transtime: y_base + (v_offs_2 + 2.0) * scale, 264 }, 265 ), 266 ) 267 bs.timer( 268 tdelay + delay3, 269 bs.WeakCall( 270 self._safe_animate, 271 s_txt.position_combine, 272 'input0', 273 { 274 0: ts_h_offs + 80.0 * scale, 275 transtime2: ts_h_offs + (80.0 - slide_amt) * scale, 276 }, 277 ), 278 ) 279 280 score_change = ( 281 player.team.sessionteam.customdata['score'] 282 - player.team.sessionteam.customdata['previous_score'] 283 ) 284 if score_change > 0: 285 xval = 113 286 yval = 3.0 287 s_txt_2 = _scoretxt( 288 '+' + str(score_change), 289 xval, 290 yval, 291 True, 292 0, 293 0.7, 294 flash=True, 295 ) 296 bs.timer( 297 tdelay + delay2, 298 bs.WeakCall( 299 self._safe_animate, 300 s_txt_2.position_combine, 301 'input1', 302 { 303 0: y_base + (v_offs + yval + 2.0) * scale, 304 transtime: y_base + (v_offs_2 + yval + 2.0) * scale, 305 }, 306 ), 307 ) 308 bs.timer( 309 tdelay + delay3, 310 bs.WeakCall( 311 self._safe_animate, 312 s_txt_2.position_combine, 313 'input0', 314 { 315 0: ts_h_offs + xval * scale, 316 transtime2: ts_h_offs + (xval - slide_amt) * scale, 317 }, 318 ), 319 ) 320 321 def _safesetattr( 322 node: bs.Node | None, attr: str, value: Any 323 ) -> None: 324 if node: 325 setattr(node, attr, value) 326 327 bs.timer( 328 tdelay + delay1, 329 bs.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), 330 ) 331 for j in range(score_change): 332 bs.timer( 333 (tdelay + delay1 + 0.15 * j), 334 bs.Call( 335 _safesetattr, 336 s_txt.node, 337 'text', 338 str( 339 player.team.sessionteam.customdata[ 340 'previous_score' 341 ] 342 + j 343 + 1 344 ), 345 ), 346 ) 347 tfin = tdelay + delay1 + 0.15 * j 348 if tfin not in sound_times: 349 sound_times.add(tfin) 350 bs.timer(tfin, self._score_display_sound_small.play) 351 v_offs -= spacing
Called once the previous 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
- bascenev1._activitytypes.ScoreScreenActivity
- inherits_tint
- inherits_vr_camera_offset
- use_fixed_vr_overlay
- default_music
- on_player_join
- on_transition_in
- bascenev1._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
- paused_text
- preloads
- lobby
- context
- 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
- bascenev1._dependency.DependencyComponent
- dep_is_present
- get_dynamic_deps