bascenev1lib.tutorial
Wrangles the game tutorial sequence.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Wrangles the game tutorial sequence.""" 4 5# Not too concerned with keeping this old module pretty; 6# don't expect to be revisiting it. 7# pylint: disable=too-many-branches 8# pylint: disable=too-many-statements 9# pylint: disable=too-many-lines 10# pylint: disable=missing-function-docstring, missing-class-docstring 11# pylint: disable=too-many-locals 12# pylint: disable=unused-argument 13# pylint: disable=unused-variable 14 15from __future__ import annotations 16 17import math 18import logging 19from collections import deque 20from typing import TYPE_CHECKING, override 21 22import bascenev1 as bs 23 24from bascenev1lib.actor.spaz import Spaz 25 26if TYPE_CHECKING: 27 from typing import Any, Callable, Sequence 28 29 30def _safesetattr(node: bs.Node | None, attr: str, value: Any) -> None: 31 if node: 32 setattr(node, attr, value) 33 34 35class ButtonPress: 36 def __init__( 37 self, 38 button: str, 39 delay: int = 0, 40 release: bool = True, 41 release_delay: int = 0, 42 ): 43 self._button = button 44 self._delay = delay 45 self._release = release 46 self._release_delay = release_delay 47 48 def run(self, a: TutorialActivity) -> None: 49 s = a.current_spaz 50 assert s is not None 51 img: bs.Node | None 52 release_call: Callable[[], None] | None 53 color: Sequence[float] | None 54 if self._button == 'punch': 55 call = s.on_punch_press 56 release_call = s.on_punch_release 57 img = a.punch_image 58 color = a.punch_image_color 59 elif self._button == 'jump': 60 call = s.on_jump_press 61 release_call = s.on_jump_release 62 img = a.jump_image 63 color = a.jump_image_color 64 elif self._button == 'bomb': 65 call = s.on_bomb_press 66 release_call = s.on_bomb_release 67 img = a.bomb_image 68 color = a.bomb_image_color 69 elif self._button == 'pickUp': 70 call = s.on_pickup_press 71 release_call = s.on_pickup_release 72 img = a.pickup_image 73 color = a.pickup_image_color 74 elif self._button == 'run': 75 call = bs.Call(s.on_run, 1.0) 76 release_call = bs.Call(s.on_run, 0.0) 77 img = None 78 color = None 79 else: 80 raise RuntimeError(f'invalid button: {self._button}') 81 82 brightness = 4.0 83 if color is not None: 84 c_bright = list(color) 85 c_bright[0] *= brightness 86 c_bright[1] *= brightness 87 c_bright[2] *= brightness 88 else: 89 c_bright = [1.0, 1.0, 1.0] 90 91 if self._delay == 0: 92 call() 93 if img is not None: 94 img.color = c_bright 95 img.vr_depth = -40 96 else: 97 bs.timer(self._delay / 1000.0, call) 98 if img is not None: 99 bs.timer( 100 self._delay / 1000.0, 101 bs.Call(_safesetattr, img, 'color', c_bright), 102 ) 103 bs.timer( 104 self._delay / 1000.0, 105 bs.Call(_safesetattr, img, 'vr_depth', -30), 106 ) 107 if self._release: 108 if self._delay == 0 and self._release_delay == 0: 109 release_call() 110 else: 111 bs.timer( 112 0.001 * (self._delay + self._release_delay), release_call 113 ) 114 if img is not None: 115 bs.timer( 116 (self._delay + self._release_delay + 100) / 1000.0, 117 bs.Call(_safesetattr, img, 'color', color), 118 ) 119 bs.timer( 120 (self._delay + self._release_delay + 100) / 1000.0, 121 bs.Call(_safesetattr, img, 'vr_depth', -20), 122 ) 123 124 125class ButtonRelease: 126 def __init__(self, button: str, delay: int = 0): 127 self._button = button 128 self._delay = delay 129 130 def run(self, a: TutorialActivity) -> None: 131 s = a.current_spaz 132 assert s is not None 133 call: Callable[[], None] | None 134 img: bs.Node | None 135 color: Sequence[float] | None 136 if self._button == 'punch': 137 call = s.on_punch_release 138 img = a.punch_image 139 color = a.punch_image_color 140 elif self._button == 'jump': 141 call = s.on_jump_release 142 img = a.jump_image 143 color = a.jump_image_color 144 elif self._button == 'bomb': 145 call = s.on_bomb_release 146 img = a.bomb_image 147 color = a.bomb_image_color 148 elif self._button == 'pickUp': 149 call = s.on_pickup_press 150 img = a.pickup_image 151 color = a.pickup_image_color 152 elif self._button == 'run': 153 call = bs.Call(s.on_run, 0.0) 154 img = None 155 color = None 156 else: 157 raise RuntimeError('invalid button: ' + self._button) 158 if self._delay == 0: 159 call() 160 else: 161 bs.timer(self._delay / 1000.0, call) 162 if img is not None: 163 bs.timer( 164 (self._delay + 100) / 1000.0, 165 bs.Call(_safesetattr, img, 'color', color), 166 ) 167 bs.timer( 168 (self._delay + 100 / 1000.0), 169 bs.Call(_safesetattr, img, 'vr_depth', -20), 170 ) 171 172 173class Player(bs.Player['Team']): 174 """Our player type for this game.""" 175 176 def __init__(self) -> None: 177 self.pressed = False 178 179 180class Team(bs.Team[Player]): 181 """Our team type for this game.""" 182 183 def __init__(self) -> None: 184 pass 185 186 187class TutorialActivity(bs.Activity[Player, Team]): 188 def __init__(self, settings: dict | None = None): 189 from bascenev1lib.maps import Rampage 190 191 if settings is None: 192 settings = {} 193 super().__init__(settings) 194 self.current_spaz: Spaz | None = None 195 self._benchmark_type = getattr(bs.getsession(), 'benchmark_type', None) 196 self.last_start_time: int | None = None 197 self.cycle_times: list[int] = [] 198 self.allow_pausing = True 199 self.allow_kick_idle_players = False 200 self._issued_warning = False 201 self._map_type = Rampage 202 self._map_type.preload() 203 self._jump_button_tex = bs.gettexture('buttonJump') 204 self._pick_up_button_tex = bs.gettexture('buttonPickUp') 205 self._bomb_button_tex = bs.gettexture('buttonBomb') 206 self._punch_button_tex = bs.gettexture('buttonPunch') 207 self._r = 'tutorial' 208 self._have_skipped = False 209 self.stick_image_position_x = self.stick_image_position_y = 0.0 210 self.spawn_sound = bs.getsound('spawn') 211 self.map: bs.Map | None = None 212 self.text: bs.Node | None = None 213 self._skip_text: bs.Node | None = None 214 self._skip_count_text: bs.Node | None = None 215 self._scale: float | None = None 216 self._stick_base_position: tuple[float, float] = (0.0, 0.0) 217 self._stick_nub_position: tuple[float, float] = (0.0, 0.0) 218 self._stick_base_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 219 self._stick_nub_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 220 self._time: int = -1 221 self.punch_image_color = (1.0, 1.0, 1.0) 222 self.punch_image: bs.Node | None = None 223 self.bomb_image: bs.Node | None = None 224 self.jump_image: bs.Node | None = None 225 self.pickup_image: bs.Node | None = None 226 self._stick_base_image: bs.Node | None = None 227 self._stick_nub_image: bs.Node | None = None 228 self.bomb_image_color = (1.0, 1.0, 1.0) 229 self.pickup_image_color = (1.0, 1.0, 1.0) 230 self.control_ui_nodes: list[bs.Node] = [] 231 self.spazzes: dict[int, Spaz] = {} 232 self.jump_image_color = (1.0, 1.0, 1.0) 233 self._entries: deque[Any] = deque() 234 self._read_entries_timer: bs.Timer | None = None 235 self._entry_timer: bs.Timer | None = None 236 237 @override 238 def on_transition_in(self) -> None: 239 super().on_transition_in() 240 bs.setmusic(bs.MusicType.CHAR_SELECT, continuous=True) 241 self.map = self._map_type() 242 243 @override 244 def on_begin(self) -> None: 245 super().on_begin() 246 247 bs.set_analytics_screen('Tutorial Start') 248 bs.increment_analytics_count('Tutorial start') 249 250 if bool(False): 251 # Buttons on top. 252 text_y = 140 253 buttons_y = 250 254 else: 255 # Buttons on bottom. 256 text_y = 260 257 buttons_y = 160 258 259 # Need different versions of this: taps/buttons/keys. 260 self.text = bs.newnode( 261 'text', 262 attrs={ 263 'text': '', 264 'scale': 1.9, 265 'position': (0, text_y), 266 'maxwidth': 500, 267 'flatness': 0.0, 268 'shadow': 0.5, 269 'h_align': 'center', 270 'v_align': 'center', 271 'v_attach': 'center', 272 }, 273 ) 274 275 # Need different versions of this: taps/buttons/keys. 276 txt = ( 277 bs.Lstr(resource=f'{self._r}.cpuBenchmarkText') 278 if self._benchmark_type == 'cpu' 279 else bs.Lstr(resource=f'{self._r}.toSkipPressAnythingText') 280 ) 281 t = self._skip_text = bs.newnode( 282 'text', 283 attrs={ 284 'text': txt, 285 'maxwidth': 900, 286 'scale': 1.1, 287 'vr_depth': 100, 288 'position': (0, 30), 289 'h_align': 'center', 290 'v_align': 'center', 291 'v_attach': 'bottom', 292 }, 293 ) 294 bs.animate(t, 'opacity', {1.0: 0.0, 2.0: 0.7}) 295 self._skip_count_text = bs.newnode( 296 'text', 297 attrs={ 298 'text': '', 299 'scale': 1.4, 300 'vr_depth': 90, 301 'position': (0, 70), 302 'h_align': 'center', 303 'v_align': 'center', 304 'v_attach': 'bottom', 305 }, 306 ) 307 308 ouya = False 309 310 self._scale = scale = 0.6 311 center_offs = 130.0 * scale 312 offs = 65.0 * scale 313 position = (0, buttons_y) 314 image_size = 90.0 * scale 315 image_size_2 = 220.0 * scale 316 nub_size = 110.0 * scale 317 p = (position[0] + center_offs, position[1] - offs) 318 319 def _sc(r: float, g: float, b: float) -> tuple[float, float, float]: 320 return 0.6 * r, 0.6 * g, 0.6 * b 321 322 self.jump_image_color = c = _sc(0.4, 1, 0.4) 323 self.jump_image = bs.newnode( 324 'image', 325 attrs={ 326 'texture': self._jump_button_tex, 327 'absolute_scale': True, 328 'vr_depth': -20, 329 'position': p, 330 'scale': (image_size, image_size), 331 'color': c, 332 }, 333 ) 334 p = (position[0] + center_offs - offs, position[1]) 335 self.punch_image_color = c = ( 336 _sc(0.2, 0.6, 1) if ouya else _sc(1, 0.7, 0.3) 337 ) 338 self.punch_image = bs.newnode( 339 'image', 340 attrs={ 341 'texture': bs.gettexture('buttonPunch'), 342 'absolute_scale': True, 343 'vr_depth': -20, 344 'position': p, 345 'scale': (image_size, image_size), 346 'color': c, 347 }, 348 ) 349 p = (position[0] + center_offs + offs, position[1]) 350 self.bomb_image_color = c = _sc(1, 0.3, 0.3) 351 self.bomb_image = bs.newnode( 352 'image', 353 attrs={ 354 'texture': bs.gettexture('buttonBomb'), 355 'absolute_scale': True, 356 'vr_depth': -20, 357 'position': p, 358 'scale': (image_size, image_size), 359 'color': c, 360 }, 361 ) 362 p = (position[0] + center_offs, position[1] + offs) 363 self.pickup_image_color = c = ( 364 _sc(1, 0.8, 0.3) if ouya else _sc(0.5, 0.5, 1) 365 ) 366 self.pickup_image = bs.newnode( 367 'image', 368 attrs={ 369 'texture': bs.gettexture('buttonPickUp'), 370 'absolute_scale': True, 371 'vr_depth': -20, 372 'position': p, 373 'scale': (image_size, image_size), 374 'color': c, 375 }, 376 ) 377 378 self._stick_base_position = p = (position[0] - center_offs, position[1]) 379 self._stick_base_image_color = c2 = (0.25, 0.25, 0.25, 1.0) 380 self._stick_base_image = bs.newnode( 381 'image', 382 attrs={ 383 'texture': bs.gettexture('nub'), 384 'absolute_scale': True, 385 'vr_depth': -40, 386 'position': p, 387 'scale': (image_size_2, image_size_2), 388 'color': c2, 389 }, 390 ) 391 self._stick_nub_position = p = (position[0] - center_offs, position[1]) 392 self._stick_nub_image_color = c3 = (0.4, 0.4, 0.4, 1.0) 393 self._stick_nub_image = bs.newnode( 394 'image', 395 attrs={ 396 'texture': bs.gettexture('nub'), 397 'absolute_scale': True, 398 'position': p, 399 'scale': (nub_size, nub_size), 400 'color': c3, 401 }, 402 ) 403 self.control_ui_nodes = [ 404 self.jump_image, 405 self.punch_image, 406 self.bomb_image, 407 self.pickup_image, 408 self._stick_base_image, 409 self._stick_nub_image, 410 ] 411 for n in self.control_ui_nodes: 412 n.opacity = 0.0 413 self._read_entries() 414 415 def set_stick_image_position(self, x: float, y: float) -> None: 416 # Clamp this to a circle. 417 len_squared = x * x + y * y 418 if len_squared > 1.0: 419 length = math.sqrt(len_squared) 420 mult = 1.0 / length 421 x *= mult 422 y *= mult 423 424 self.stick_image_position_x = x 425 self.stick_image_position_y = y 426 offs = 50.0 427 assert self._scale is not None 428 p = [ 429 self._stick_nub_position[0] + x * offs * self._scale, 430 self._stick_nub_position[1] + y * offs * self._scale, 431 ] 432 c = list(self._stick_nub_image_color) 433 if abs(x) > 0.1 or abs(y) > 0.1: 434 c[0] *= 2.0 435 c[1] *= 4.0 436 c[2] *= 2.0 437 assert self._stick_nub_image is not None 438 self._stick_nub_image.position = p 439 self._stick_nub_image.color = c 440 c = list(self._stick_base_image_color) 441 if abs(x) > 0.1 or abs(y) > 0.1: 442 c[0] *= 1.5 443 c[1] *= 1.5 444 c[2] *= 1.5 445 assert self._stick_base_image is not None 446 self._stick_base_image.color = c 447 448 def _read_entries(self) -> None: 449 try: 450 451 class Reset: 452 def __init__(self) -> None: 453 pass 454 455 def run(self, a: TutorialActivity) -> None: 456 # if we're looping, print out how long each cycle took 457 # print out how long each cycle took.. 458 if a.last_start_time is not None: 459 tval = int(bs.apptime() * 1000.0) - a.last_start_time 460 assert isinstance(tval, int) 461 diff = tval 462 a.cycle_times.append(diff) 463 bs.broadcastmessage( 464 'cycle time: ' 465 + str(diff) 466 + ' (average: ' 467 + str(sum(a.cycle_times) / len(a.cycle_times)) 468 + ')' 469 ) 470 tval = int(bs.apptime() * 1000.0) 471 assert isinstance(tval, int) 472 a.last_start_time = tval 473 474 assert a.text 475 a.text.text = '' 476 for spaz in list(a.spazzes.values()): 477 spaz.handlemessage(bs.DieMessage(immediate=True)) 478 a.spazzes = {} 479 a.current_spaz = None 480 for n in a.control_ui_nodes: 481 n.opacity = 0.0 482 a.set_stick_image_position(0, 0) 483 484 # Can be used for debugging. 485 class SetSpeed: 486 def __init__(self, speed: int): 487 self._speed = speed 488 489 def run(self, a: TutorialActivity) -> None: 490 print('setting to', self._speed) 491 bs.set_debug_speed_exponent(self._speed) 492 493 class RemoveGloves: 494 def __init__(self) -> None: 495 pass 496 497 def run(self, a: TutorialActivity) -> None: 498 # pylint: disable=protected-access 499 assert a.current_spaz is not None 500 # noinspection PyProtectedMember 501 a.current_spaz._gloves_wear_off() 502 503 class KillSpaz: 504 def __init__(self, num: int, explode: bool = False): 505 self._num = num 506 self._explode = explode 507 508 def run(self, a: TutorialActivity) -> None: 509 if self._explode: 510 a.spazzes[self._num].shatter() 511 del a.spazzes[self._num] 512 513 class SpawnSpaz: 514 def __init__( 515 self, 516 num: int, 517 position: Sequence[float], 518 color: Sequence[float] = (1.0, 1.0, 1.0), 519 make_current: bool = False, 520 relative_to: int | None = None, 521 name: str | bs.Lstr = '', 522 flash: bool = True, 523 angle: float = 0.0, 524 ): 525 self._num = num 526 self._position = position 527 self._make_current = make_current 528 self._color = color 529 self._relative_to = relative_to 530 self._name = name 531 self._flash = flash 532 self._angle = angle 533 534 def run(self, a: TutorialActivity) -> None: 535 # if they gave a 'relative to' spaz, position is relative 536 # to them 537 pos: Sequence[float] 538 if self._relative_to is not None: 539 snode = a.spazzes[self._relative_to].node 540 assert snode 541 their_pos = snode.position 542 pos = ( 543 their_pos[0] + self._position[0], 544 their_pos[1] + self._position[1], 545 their_pos[2] + self._position[2], 546 ) 547 else: 548 pos = self._position 549 550 # if there's already a spaz at this spot, insta-kill it 551 if self._num in a.spazzes: 552 a.spazzes[self._num].handlemessage( 553 bs.DieMessage(immediate=True) 554 ) 555 556 s = a.spazzes[self._num] = Spaz( 557 color=self._color, 558 start_invincible=self._flash, 559 demo_mode=True, 560 ) 561 562 # FIXME: Should extend spaz to support Lstr names. 563 assert s.node 564 if isinstance(self._name, bs.Lstr): 565 s.node.name = self._name.evaluate() 566 else: 567 s.node.name = self._name 568 s.node.name_color = self._color 569 s.handlemessage(bs.StandMessage(pos, self._angle)) 570 if self._make_current: 571 a.current_spaz = s 572 if self._flash: 573 a.spawn_sound.play(position=pos) 574 575 class Powerup: 576 def __init__( 577 self, 578 num: int, 579 position: Sequence[float], 580 color: Sequence[float] = (1.0, 1.0, 1.0), 581 make_current: bool = False, 582 relative_to: int | None = None, 583 ): 584 self._position = position 585 self._relative_to = relative_to 586 587 def run(self, a: TutorialActivity) -> None: 588 # If they gave a 'relative to' spaz, position is relative 589 # to them. 590 pos: Sequence[float] 591 if self._relative_to is not None: 592 snode = a.spazzes[self._relative_to].node 593 assert snode 594 their_pos = snode.position 595 pos = ( 596 their_pos[0] + self._position[0], 597 their_pos[1] + self._position[1], 598 their_pos[2] + self._position[2], 599 ) 600 else: 601 pos = self._position 602 from bascenev1lib.actor import powerupbox 603 604 powerupbox.PowerupBox( 605 position=pos, poweruptype='punch' 606 ).autoretain() 607 608 class Delay: 609 def __init__(self, time: int) -> None: 610 self._time = time 611 612 def run(self, a: TutorialActivity) -> int: 613 return self._time 614 615 class AnalyticsScreen: 616 def __init__(self, screen: str) -> None: 617 self._screen = screen 618 619 def run(self, a: TutorialActivity) -> None: 620 bs.set_analytics_screen(self._screen) 621 622 class DelayOld: 623 def __init__(self, time: int) -> None: 624 self._time = time 625 626 def run(self, a: TutorialActivity) -> int: 627 return int(0.9 * self._time) 628 629 class DelayOld2: 630 def __init__(self, time: int) -> None: 631 self._time = time 632 633 def run(self, a: TutorialActivity) -> int: 634 return int(0.8 * self._time) 635 636 class End: 637 def __init__(self) -> None: 638 pass 639 640 def run(self, a: TutorialActivity) -> None: 641 bs.increment_analytics_count('Tutorial finish') 642 a.end() 643 644 class Move: 645 def __init__(self, x: float, y: float): 646 self._x = float(x) 647 self._y = float(y) 648 649 def run(self, a: TutorialActivity) -> None: 650 s = a.current_spaz 651 assert s 652 # FIXME: Game should take floats for this. 653 x_clamped = self._x 654 y_clamped = self._y 655 s.on_move_left_right(x_clamped) 656 s.on_move_up_down(y_clamped) 657 a.set_stick_image_position(self._x, self._y) 658 659 class MoveLR: 660 def __init__(self, x: float): 661 self._x = float(x) 662 663 def run(self, a: TutorialActivity) -> None: 664 s = a.current_spaz 665 assert s 666 # FIXME: Game should take floats for this. 667 x_clamped = self._x 668 s.on_move_left_right(x_clamped) 669 a.set_stick_image_position( 670 self._x, a.stick_image_position_y 671 ) 672 673 class MoveUD: 674 def __init__(self, y: float): 675 self._y = float(y) 676 677 def run(self, a: TutorialActivity) -> None: 678 s = a.current_spaz 679 assert s 680 # FIXME: Game should take floats for this. 681 y_clamped = self._y 682 s.on_move_up_down(y_clamped) 683 a.set_stick_image_position( 684 a.stick_image_position_x, self._y 685 ) 686 687 class Bomb(ButtonPress): 688 def __init__( 689 self, 690 delay: int = 0, 691 release: bool = True, 692 release_delay: int = 500, 693 ): 694 ButtonPress.__init__( 695 self, 696 'bomb', 697 delay=delay, 698 release=release, 699 release_delay=release_delay, 700 ) 701 702 class Jump(ButtonPress): 703 def __init__( 704 self, 705 delay: int = 0, 706 release: bool = True, 707 release_delay: int = 500, 708 ): 709 ButtonPress.__init__( 710 self, 711 'jump', 712 delay=delay, 713 release=release, 714 release_delay=release_delay, 715 ) 716 717 class Punch(ButtonPress): 718 def __init__( 719 self, 720 delay: int = 0, 721 release: bool = True, 722 release_delay: int = 500, 723 ): 724 ButtonPress.__init__( 725 self, 726 'punch', 727 delay=delay, 728 release=release, 729 release_delay=release_delay, 730 ) 731 732 class PickUp(ButtonPress): 733 def __init__( 734 self, 735 delay: int = 0, 736 release: bool = True, 737 release_delay: int = 500, 738 ): 739 ButtonPress.__init__( 740 self, 741 'pickUp', 742 delay=delay, 743 release=release, 744 release_delay=release_delay, 745 ) 746 747 class Run(ButtonPress): 748 def __init__( 749 self, 750 delay: int = 0, 751 release: bool = True, 752 release_delay: int = 500, 753 ): 754 ButtonPress.__init__( 755 self, 756 'run', 757 delay=delay, 758 release=release, 759 release_delay=release_delay, 760 ) 761 762 class BombRelease(ButtonRelease): 763 def __init__(self, delay: int = 0): 764 super().__init__('bomb', delay=delay) 765 766 class JumpRelease(ButtonRelease): 767 def __init__(self, delay: int = 0): 768 super().__init__('jump', delay=delay) 769 770 class PunchRelease(ButtonRelease): 771 def __init__(self, delay: int = 0): 772 super().__init__('punch', delay=delay) 773 774 class PickUpRelease(ButtonRelease): 775 def __init__(self, delay: int = 0): 776 super().__init__('pickUp', delay=delay) 777 778 class RunRelease(ButtonRelease): 779 def __init__(self, delay: int = 0): 780 super().__init__('run', delay=delay) 781 782 class ShowControls: 783 def __init__(self) -> None: 784 pass 785 786 def run(self, a: TutorialActivity) -> None: 787 for n in a.control_ui_nodes: 788 bs.animate(n, 'opacity', {0.0: 0.0, 1.0: 1.0}) 789 790 class Text: 791 def __init__(self, text: str | bs.Lstr): 792 self.text = text 793 794 def run(self, a: TutorialActivity) -> None: 795 assert a.text 796 a.text.text = self.text 797 798 class PrintPos: 799 def __init__(self, spaz_num: int | None = None): 800 self._spaz_num = spaz_num 801 802 def run(self, a: TutorialActivity) -> None: 803 if self._spaz_num is None: 804 s = a.current_spaz 805 else: 806 s = a.spazzes[self._spaz_num] 807 assert s and s.node 808 t = list(s.node.position) 809 print('RestorePos(' + str((t[0], t[1] - 1.0, t[2])) + '),') 810 811 class RestorePos: 812 def __init__(self, pos: Sequence[float]) -> None: 813 self._pos = pos 814 815 def run(self, a: TutorialActivity) -> None: 816 s = a.current_spaz 817 assert s 818 s.handlemessage(bs.StandMessage(self._pos, 0)) 819 820 class Celebrate: 821 def __init__( 822 self, 823 celebrate_type: str = 'both', 824 spaz_num: int | None = None, 825 duration: int = 1000, 826 ): 827 self._spaz_num = spaz_num 828 self._celebrate_type = celebrate_type 829 self._duration = duration 830 831 def run(self, a: TutorialActivity) -> None: 832 if self._spaz_num is None: 833 s = a.current_spaz 834 else: 835 s = a.spazzes[self._spaz_num] 836 assert s and s.node 837 if self._celebrate_type == 'right': 838 s.node.handlemessage('celebrate_r', self._duration) 839 elif self._celebrate_type == 'left': 840 s.node.handlemessage('celebrate_l', self._duration) 841 elif self._celebrate_type == 'both': 842 s.node.handlemessage('celebrate', self._duration) 843 else: 844 raise RuntimeError( 845 'invalid celebrate type ' + self._celebrate_type 846 ) 847 848 self._entries = deque( 849 [ 850 Reset(), 851 SpawnSpaz(0, (0, 5.5, -3.0), make_current=True), 852 DelayOld(1000), 853 AnalyticsScreen('Tutorial Section 1'), 854 Text( 855 bs.Lstr(resource=f'{self._r}.phrase01Text') 856 ), # hi there 857 Celebrate('left'), 858 DelayOld(2000), 859 Text( 860 bs.Lstr( 861 resource=f'{self._r}.phrase02Text', 862 subs=[ 863 ('${APP_NAME}', bs.Lstr(resource='titleText')) 864 ], 865 ) 866 ), # welcome to <appname> 867 DelayOld(80), 868 Run(release=False), 869 Jump(release=False), 870 MoveLR(1), 871 MoveUD(0), 872 DelayOld(70), 873 RunRelease(), 874 JumpRelease(), 875 DelayOld(60), 876 MoveUD(1), 877 DelayOld(30), 878 MoveLR(0), 879 DelayOld(90), 880 MoveLR(-1), 881 DelayOld(20), 882 MoveUD(0), 883 DelayOld(70), 884 MoveUD(-1), 885 DelayOld(20), 886 MoveLR(0), 887 DelayOld(80), 888 MoveUD(0), 889 DelayOld(1500), 890 Text( 891 bs.Lstr(resource=f'{self._r}.phrase03Text') 892 ), # here's a few tips 893 DelayOld(1000), 894 ShowControls(), 895 DelayOld(1000), 896 Jump(), 897 DelayOld(1000), 898 Jump(), 899 DelayOld(1000), 900 AnalyticsScreen('Tutorial Section 2'), 901 Text( 902 bs.Lstr( 903 resource=f'{self._r}.phrase04Text', 904 subs=[ 905 ('${APP_NAME}', bs.Lstr(resource='titleText')) 906 ], 907 ) 908 ), # many things are based on physics 909 DelayOld(20), 910 MoveUD(0), 911 DelayOld(60), 912 MoveLR(0), 913 DelayOld(10), 914 MoveLR(0), 915 MoveUD(0), 916 DelayOld(10), 917 MoveLR(0), 918 MoveUD(0), 919 DelayOld(20), 920 MoveUD(-0.0575579), 921 DelayOld(10), 922 MoveUD(-0.207831), 923 DelayOld(30), 924 MoveUD(-0.309793), 925 DelayOld(10), 926 MoveUD(-0.474502), 927 DelayOld(10), 928 MoveLR(0.00390637), 929 MoveUD(-0.647053), 930 DelayOld(20), 931 MoveLR(-0.0745262), 932 MoveUD(-0.819605), 933 DelayOld(10), 934 MoveLR(-0.168645), 935 MoveUD(-0.937254), 936 DelayOld(30), 937 MoveLR(-0.294137), 938 MoveUD(-1), 939 DelayOld(10), 940 MoveLR(-0.411786), 941 DelayOld(10), 942 MoveLR(-0.639241), 943 DelayOld(30), 944 MoveLR(-0.75689), 945 DelayOld(10), 946 MoveLR(-0.905911), 947 DelayOld(20), 948 MoveLR(-1), 949 DelayOld(50), 950 MoveUD(-0.960784), 951 DelayOld(20), 952 MoveUD(-0.819605), 953 MoveUD(-0.61568), 954 DelayOld(20), 955 MoveUD(-0.427442), 956 DelayOld(20), 957 MoveUD(-0.231361), 958 DelayOld(10), 959 MoveUD(-0.00390637), 960 DelayOld(30), 961 MoveUD(0.333354), 962 MoveUD(0.584338), 963 DelayOld(20), 964 MoveUD(0.764733), 965 DelayOld(30), 966 MoveLR(-0.803949), 967 MoveUD(0.913755), 968 DelayOld(10), 969 MoveLR(-0.647084), 970 MoveUD(0.992187), 971 DelayOld(20), 972 MoveLR(-0.435316), 973 MoveUD(1), 974 DelayOld(20), 975 MoveLR(-0.168645), 976 MoveUD(0.976501), 977 MoveLR(0.0744957), 978 MoveUD(0.905911), 979 DelayOld(20), 980 MoveLR(0.270577), 981 MoveUD(0.843165), 982 DelayOld(20), 983 MoveLR(0.435286), 984 MoveUD(0.780419), 985 DelayOld(10), 986 MoveLR(0.66274), 987 MoveUD(0.647084), 988 DelayOld(30), 989 MoveLR(0.803919), 990 MoveUD(0.458846), 991 MoveLR(0.929411), 992 MoveUD(0.223548), 993 DelayOld(20), 994 MoveLR(0.95294), 995 MoveUD(0.137272), 996 DelayOld(20), 997 MoveLR(1), 998 MoveUD(-0.0509659), 999 DelayOld(20), 1000 MoveUD(-0.247047), 1001 DelayOld(20), 1002 MoveUD(-0.443129), 1003 DelayOld(20), 1004 MoveUD(-0.694113), 1005 MoveUD(-0.921567), 1006 DelayOld(30), 1007 MoveLR(0.858821), 1008 MoveUD(-1), 1009 DelayOld(10), 1010 MoveLR(0.68627), 1011 DelayOld(10), 1012 MoveLR(0.364696), 1013 DelayOld(20), 1014 MoveLR(0.0509659), 1015 DelayOld(20), 1016 MoveLR(-0.223548), 1017 DelayOld(10), 1018 MoveLR(-0.600024), 1019 MoveUD(-0.913724), 1020 DelayOld(30), 1021 MoveLR(-0.858852), 1022 MoveUD(-0.717643), 1023 MoveLR(-1), 1024 MoveUD(-0.474502), 1025 DelayOld(20), 1026 MoveUD(-0.396069), 1027 DelayOld(20), 1028 MoveUD(-0.286264), 1029 DelayOld(20), 1030 MoveUD(-0.137242), 1031 DelayOld(20), 1032 MoveUD(0.0353099), 1033 DelayOld(10), 1034 MoveUD(0.32551), 1035 DelayOld(20), 1036 MoveUD(0.592181), 1037 DelayOld(10), 1038 MoveUD(0.851009), 1039 DelayOld(10), 1040 MoveUD(1), 1041 DelayOld(30), 1042 MoveLR(-0.764733), 1043 DelayOld(20), 1044 MoveLR(-0.403943), 1045 MoveLR(-0.145116), 1046 DelayOld(30), 1047 MoveLR(0.0901822), 1048 MoveLR(0.32548), 1049 DelayOld(30), 1050 MoveLR(0.560778), 1051 MoveUD(0.929441), 1052 DelayOld(20), 1053 MoveLR(0.709799), 1054 MoveUD(0.73336), 1055 MoveLR(0.803919), 1056 MoveUD(0.545122), 1057 DelayOld(20), 1058 MoveLR(0.882351), 1059 MoveUD(0.356883), 1060 DelayOld(10), 1061 MoveLR(0.968627), 1062 MoveUD(0.113742), 1063 DelayOld(20), 1064 MoveLR(0.992157), 1065 MoveUD(-0.0823389), 1066 DelayOld(30), 1067 MoveUD(-0.309793), 1068 DelayOld(10), 1069 MoveUD(-0.545091), 1070 DelayOld(20), 1071 MoveLR(0.882351), 1072 MoveUD(-0.874508), 1073 DelayOld(20), 1074 MoveLR(0.756859), 1075 MoveUD(-1), 1076 DelayOld(10), 1077 MoveLR(0.576464), 1078 DelayOld(20), 1079 MoveLR(0.254891), 1080 DelayOld(10), 1081 MoveLR(-0.0274667), 1082 DelayOld(10), 1083 MoveLR(-0.356883), 1084 DelayOld(30), 1085 MoveLR(-0.592181), 1086 MoveLR(-0.827479), 1087 MoveUD(-0.921567), 1088 DelayOld(20), 1089 MoveLR(-1), 1090 MoveUD(-0.749016), 1091 DelayOld(20), 1092 MoveUD(-0.61568), 1093 DelayOld(10), 1094 MoveUD(-0.403912), 1095 DelayOld(20), 1096 MoveUD(-0.207831), 1097 DelayOld(10), 1098 MoveUD(0.121586), 1099 DelayOld(30), 1100 MoveUD(0.34904), 1101 DelayOld(10), 1102 MoveUD(0.560808), 1103 DelayOld(10), 1104 MoveUD(0.827479), 1105 DelayOld(30), 1106 MoveUD(1), 1107 DelayOld(20), 1108 MoveLR(-0.976501), 1109 MoveLR(-0.670614), 1110 DelayOld(20), 1111 MoveLR(-0.239235), 1112 DelayOld(20), 1113 MoveLR(0.160772), 1114 DelayOld(20), 1115 MoveLR(0.443129), 1116 DelayOld(10), 1117 MoveLR(0.68627), 1118 MoveUD(0.976501), 1119 DelayOld(30), 1120 MoveLR(0.929411), 1121 MoveUD(0.73336), 1122 MoveLR(1), 1123 MoveUD(0.482376), 1124 DelayOld(20), 1125 MoveUD(0.34904), 1126 DelayOld(10), 1127 MoveUD(0.160802), 1128 DelayOld(30), 1129 MoveUD(-0.0744957), 1130 DelayOld(10), 1131 MoveUD(-0.333323), 1132 DelayOld(20), 1133 MoveUD(-0.647053), 1134 DelayOld(20), 1135 MoveUD(-0.937254), 1136 DelayOld(10), 1137 MoveLR(0.858821), 1138 MoveUD(-1), 1139 DelayOld(10), 1140 MoveLR(0.576464), 1141 DelayOld(30), 1142 MoveLR(0.184301), 1143 DelayOld(10), 1144 MoveLR(-0.121586), 1145 DelayOld(10), 1146 MoveLR(-0.474532), 1147 DelayOld(30), 1148 MoveLR(-0.670614), 1149 MoveLR(-0.851009), 1150 DelayOld(30), 1151 MoveLR(-1), 1152 MoveUD(-0.968627), 1153 DelayOld(20), 1154 MoveUD(-0.843135), 1155 DelayOld(10), 1156 MoveUD(-0.631367), 1157 DelayOld(20), 1158 MoveUD(-0.403912), 1159 MoveUD(-0.176458), 1160 DelayOld(20), 1161 MoveUD(0.0902127), 1162 DelayOld(20), 1163 MoveUD(0.380413), 1164 DelayOld(10), 1165 MoveUD(0.717673), 1166 DelayOld(30), 1167 MoveUD(1), 1168 DelayOld(10), 1169 MoveLR(-0.741203), 1170 DelayOld(20), 1171 MoveLR(-0.458846), 1172 DelayOld(10), 1173 MoveLR(-0.145116), 1174 DelayOld(10), 1175 MoveLR(0.0980255), 1176 DelayOld(20), 1177 MoveLR(0.294107), 1178 DelayOld(30), 1179 MoveLR(0.466659), 1180 MoveLR(0.717643), 1181 MoveUD(0.796106), 1182 DelayOld(20), 1183 MoveLR(0.921567), 1184 MoveUD(0.443159), 1185 DelayOld(20), 1186 MoveLR(1), 1187 MoveUD(0.145116), 1188 DelayOld(10), 1189 MoveUD(-0.0274361), 1190 DelayOld(30), 1191 MoveUD(-0.223518), 1192 MoveUD(-0.427442), 1193 DelayOld(20), 1194 MoveUD(-0.874508), 1195 DelayOld(20), 1196 MoveUD(-1), 1197 DelayOld(10), 1198 MoveLR(0.929411), 1199 DelayOld(20), 1200 MoveLR(0.68627), 1201 DelayOld(20), 1202 MoveLR(0.364696), 1203 DelayOld(20), 1204 MoveLR(0.0431227), 1205 DelayOld(10), 1206 MoveLR(-0.333354), 1207 DelayOld(20), 1208 MoveLR(-0.639241), 1209 DelayOld(20), 1210 MoveLR(-0.968657), 1211 MoveUD(-0.968627), 1212 DelayOld(20), 1213 MoveLR(-1), 1214 MoveUD(-0.890194), 1215 MoveUD(-0.866665), 1216 DelayOld(20), 1217 MoveUD(-0.749016), 1218 DelayOld(20), 1219 MoveUD(-0.529405), 1220 DelayOld(20), 1221 MoveUD(-0.30195), 1222 DelayOld(10), 1223 MoveUD(-0.00390637), 1224 DelayOld(10), 1225 MoveUD(0.262764), 1226 DelayOld(30), 1227 MoveLR(-0.600024), 1228 MoveUD(0.458846), 1229 DelayOld(10), 1230 MoveLR(-0.294137), 1231 MoveUD(0.482376), 1232 DelayOld(20), 1233 MoveLR(-0.200018), 1234 MoveUD(0.505905), 1235 DelayOld(10), 1236 MoveLR(-0.145116), 1237 MoveUD(0.545122), 1238 DelayOld(20), 1239 MoveLR(-0.0353099), 1240 MoveUD(0.584338), 1241 DelayOld(20), 1242 MoveLR(0.137242), 1243 MoveUD(0.592181), 1244 DelayOld(20), 1245 MoveLR(0.30195), 1246 DelayOld(10), 1247 MoveLR(0.490188), 1248 DelayOld(10), 1249 MoveLR(0.599994), 1250 MoveUD(0.529435), 1251 DelayOld(30), 1252 MoveLR(0.66274), 1253 MoveUD(0.3961), 1254 DelayOld(20), 1255 MoveLR(0.670583), 1256 MoveUD(0.231391), 1257 MoveLR(0.68627), 1258 MoveUD(0.0745262), 1259 Move(0, -0.01), 1260 DelayOld(100), 1261 Move(0, 0), 1262 DelayOld(1000), 1263 Text( 1264 bs.Lstr(resource=f'{self._r}.phrase05Text') 1265 ), # for example when you punch.. 1266 DelayOld(510), 1267 Move(0, -0.01), 1268 DelayOld(100), 1269 Move(0, 0), 1270 DelayOld(500), 1271 SpawnSpaz( 1272 0, 1273 (-0.09249162673950195, 4.337906360626221, -2.3), 1274 make_current=True, 1275 flash=False, 1276 ), 1277 SpawnSpaz( 1278 1, 1279 (-3.1, 4.3, -2.0), 1280 make_current=False, 1281 color=(1, 1, 0.4), 1282 name=bs.Lstr(resource=f'{self._r}.randomName1Text'), 1283 ), 1284 Move(-1.0, 0), 1285 DelayOld(1050), 1286 Move(0, -0.01), 1287 DelayOld(100), 1288 Move(0, 0), 1289 DelayOld(1000), 1290 Text( 1291 bs.Lstr(resource=f'{self._r}.phrase06Text') 1292 ), # your damage is based 1293 DelayOld(1200), 1294 Move(-0.05, 0), 1295 DelayOld(200), 1296 Punch(), 1297 DelayOld(800), 1298 Punch(), 1299 DelayOld(800), 1300 Punch(), 1301 DelayOld(800), 1302 Move(0, -0.01), 1303 DelayOld(100), 1304 Move(0, 0), 1305 Text( 1306 bs.Lstr( 1307 resource=f'{self._r}.phrase07Text', 1308 subs=[ 1309 ( 1310 '${NAME}', 1311 bs.Lstr( 1312 resource=f'{self._r}.randomName1Text' 1313 ), 1314 ) 1315 ], 1316 ) 1317 ), # see that didn't hurt fred 1318 DelayOld(2000), 1319 Celebrate('right', spaz_num=1), 1320 DelayOld(1400), 1321 Text( 1322 bs.Lstr(resource=f'{self._r}.phrase08Text') 1323 ), # lets jump and spin to get more speed 1324 DelayOld(30), 1325 MoveLR(0), 1326 DelayOld(40), 1327 MoveLR(0), 1328 DelayOld(40), 1329 MoveLR(0), 1330 DelayOld(130), 1331 MoveLR(0), 1332 DelayOld(100), 1333 MoveLR(0), 1334 DelayOld(10), 1335 MoveLR(0.0480667), 1336 DelayOld(40), 1337 MoveLR(0.056093), 1338 MoveLR(0.0681173), 1339 DelayOld(30), 1340 MoveLR(0.0801416), 1341 DelayOld(10), 1342 MoveLR(0.184301), 1343 DelayOld(10), 1344 MoveLR(0.207831), 1345 DelayOld(20), 1346 MoveLR(0.231361), 1347 DelayOld(30), 1348 MoveLR(0.239204), 1349 DelayOld(30), 1350 MoveLR(0.254891), 1351 DelayOld(40), 1352 MoveLR(0.270577), 1353 DelayOld(10), 1354 MoveLR(0.30195), 1355 DelayOld(20), 1356 MoveLR(0.341166), 1357 DelayOld(30), 1358 MoveLR(0.388226), 1359 MoveLR(0.435286), 1360 DelayOld(30), 1361 MoveLR(0.490188), 1362 DelayOld(10), 1363 MoveLR(0.560778), 1364 DelayOld(20), 1365 MoveLR(0.599994), 1366 DelayOld(10), 1367 MoveLR(0.647053), 1368 DelayOld(10), 1369 MoveLR(0.68627), 1370 DelayOld(30), 1371 MoveLR(0.733329), 1372 DelayOld(20), 1373 MoveLR(0.764702), 1374 DelayOld(10), 1375 MoveLR(0.827448), 1376 DelayOld(20), 1377 MoveLR(0.874508), 1378 DelayOld(20), 1379 MoveLR(0.929411), 1380 DelayOld(10), 1381 MoveLR(1), 1382 DelayOld(830), 1383 MoveUD(0.0274667), 1384 DelayOld(10), 1385 MoveLR(0.95294), 1386 MoveUD(0.113742), 1387 DelayOld(30), 1388 MoveLR(0.780389), 1389 MoveUD(0.184332), 1390 DelayOld(10), 1391 MoveLR(0.27842), 1392 MoveUD(0.0745262), 1393 DelayOld(20), 1394 MoveLR(0), 1395 MoveUD(0), 1396 DelayOld(390), 1397 MoveLR(0), 1398 MoveLR(0), 1399 DelayOld(20), 1400 MoveLR(0), 1401 DelayOld(20), 1402 MoveLR(0), 1403 DelayOld(10), 1404 MoveLR(-0.0537431), 1405 DelayOld(20), 1406 MoveLR(-0.215705), 1407 DelayOld(30), 1408 MoveLR(-0.388256), 1409 MoveLR(-0.529435), 1410 DelayOld(30), 1411 MoveLR(-0.694143), 1412 DelayOld(20), 1413 MoveLR(-0.851009), 1414 MoveUD(0.0588397), 1415 DelayOld(10), 1416 MoveLR(-1), 1417 MoveUD(0.0745262), 1418 Run(release=False), 1419 DelayOld(200), 1420 MoveUD(0.0509964), 1421 DelayOld(30), 1422 MoveUD(0.0117801), 1423 DelayOld(20), 1424 MoveUD(-0.0901822), 1425 MoveUD(-0.372539), 1426 DelayOld(30), 1427 MoveLR(-0.898068), 1428 MoveUD(-0.890194), 1429 Jump(release=False), 1430 DelayOld(20), 1431 MoveLR(-0.647084), 1432 MoveUD(-1), 1433 MoveLR(-0.427473), 1434 DelayOld(20), 1435 MoveLR(-0.00393689), 1436 DelayOld(10), 1437 MoveLR(0.537248), 1438 DelayOld(30), 1439 MoveLR(1), 1440 DelayOld(50), 1441 RunRelease(), 1442 JumpRelease(), 1443 DelayOld(50), 1444 MoveUD(-0.921567), 1445 MoveUD(-0.749016), 1446 DelayOld(30), 1447 MoveUD(-0.552934), 1448 DelayOld(10), 1449 MoveUD(-0.247047), 1450 DelayOld(20), 1451 MoveUD(0.200018), 1452 DelayOld(20), 1453 MoveUD(0.670614), 1454 MoveUD(1), 1455 DelayOld(70), 1456 MoveLR(0.97647), 1457 DelayOld(20), 1458 MoveLR(0.764702), 1459 DelayOld(20), 1460 MoveLR(0.364696), 1461 DelayOld(20), 1462 MoveLR(0.00390637), 1463 MoveLR(-0.309824), 1464 DelayOld(20), 1465 MoveLR(-0.576495), 1466 DelayOld(30), 1467 MoveLR(-0.898068), 1468 DelayOld(10), 1469 MoveLR(-1), 1470 MoveUD(0.905911), 1471 DelayOld(20), 1472 MoveUD(0.498062), 1473 DelayOld(20), 1474 MoveUD(0.0274667), 1475 MoveUD(-0.403912), 1476 DelayOld(20), 1477 MoveUD(-1), 1478 Run(release=False), 1479 Jump(release=False), 1480 DelayOld(10), 1481 Punch(release=False), 1482 DelayOld(70), 1483 JumpRelease(), 1484 DelayOld(110), 1485 MoveLR(-0.976501), 1486 RunRelease(), 1487 PunchRelease(), 1488 DelayOld(10), 1489 MoveLR(-0.952971), 1490 DelayOld(20), 1491 MoveLR(-0.905911), 1492 MoveLR(-0.827479), 1493 DelayOld(20), 1494 MoveLR(-0.75689), 1495 DelayOld(30), 1496 MoveLR(-0.73336), 1497 MoveLR(-0.694143), 1498 DelayOld(20), 1499 MoveLR(-0.670614), 1500 DelayOld(30), 1501 MoveLR(-0.66277), 1502 DelayOld(10), 1503 MoveUD(-0.960784), 1504 DelayOld(20), 1505 MoveLR(-0.623554), 1506 MoveUD(-0.874508), 1507 DelayOld(10), 1508 MoveLR(-0.545122), 1509 MoveUD(-0.694113), 1510 DelayOld(20), 1511 MoveLR(-0.505905), 1512 MoveUD(-0.474502), 1513 DelayOld(20), 1514 MoveLR(-0.458846), 1515 MoveUD(-0.356853), 1516 MoveLR(-0.364727), 1517 MoveUD(-0.27842), 1518 DelayOld(20), 1519 MoveLR(0.00390637), 1520 Move(0, 0), 1521 DelayOld(1000), 1522 Text( 1523 bs.Lstr(resource=f'{self._r}.phrase09Text') 1524 ), # ah that's better 1525 DelayOld(1900), 1526 AnalyticsScreen('Tutorial Section 3'), 1527 Text( 1528 bs.Lstr(resource=f'{self._r}.phrase10Text') 1529 ), # running also helps 1530 DelayOld(100), 1531 SpawnSpaz( 1532 0, (-3.2, 4.3, -4.4), make_current=True, flash=False 1533 ), 1534 SpawnSpaz( 1535 1, 1536 (3.3, 4.2, -5.8), 1537 make_current=False, 1538 color=(0.9, 0.5, 1.0), 1539 name=bs.Lstr(resource=f'{self._r}.randomName2Text'), 1540 ), 1541 DelayOld(1800), 1542 Text( 1543 bs.Lstr(resource=f'{self._r}.phrase11Text') 1544 ), # hold ANY button to run 1545 DelayOld(300), 1546 MoveUD(0), 1547 DelayOld(20), 1548 MoveUD(-0.0520646), 1549 DelayOld(20), 1550 MoveLR(0), 1551 MoveUD(-0.223518), 1552 Run(release=False), 1553 Jump(release=False), 1554 DelayOld(10), 1555 MoveLR(0.0980255), 1556 MoveUD(-0.309793), 1557 DelayOld(30), 1558 MoveLR(0.160772), 1559 MoveUD(-0.427442), 1560 DelayOld(20), 1561 MoveLR(0.231361), 1562 MoveUD(-0.545091), 1563 DelayOld(10), 1564 MoveLR(0.317637), 1565 MoveUD(-0.678426), 1566 DelayOld(20), 1567 MoveLR(0.396069), 1568 MoveUD(-0.819605), 1569 MoveLR(0.482345), 1570 MoveUD(-0.913724), 1571 DelayOld(20), 1572 MoveLR(0.560778), 1573 MoveUD(-1), 1574 DelayOld(20), 1575 MoveLR(0.607837), 1576 DelayOld(10), 1577 MoveLR(0.623524), 1578 DelayOld(30), 1579 MoveLR(0.647053), 1580 DelayOld(20), 1581 MoveLR(0.670583), 1582 MoveLR(0.694113), 1583 DelayOld(30), 1584 MoveLR(0.733329), 1585 DelayOld(20), 1586 MoveLR(0.764702), 1587 MoveLR(0.788232), 1588 DelayOld(20), 1589 MoveLR(0.827448), 1590 DelayOld(10), 1591 MoveLR(0.858821), 1592 DelayOld(20), 1593 MoveLR(0.921567), 1594 DelayOld(30), 1595 MoveLR(0.97647), 1596 MoveLR(1), 1597 DelayOld(130), 1598 MoveUD(-0.960784), 1599 DelayOld(20), 1600 MoveUD(-0.921567), 1601 DelayOld(30), 1602 MoveUD(-0.866665), 1603 MoveUD(-0.819605), 1604 DelayOld(30), 1605 MoveUD(-0.772546), 1606 MoveUD(-0.725486), 1607 DelayOld(30), 1608 MoveUD(-0.631367), 1609 DelayOld(10), 1610 MoveUD(-0.552934), 1611 DelayOld(20), 1612 MoveUD(-0.474502), 1613 DelayOld(10), 1614 MoveUD(-0.403912), 1615 DelayOld(30), 1616 MoveUD(-0.356853), 1617 DelayOld(30), 1618 MoveUD(-0.34901), 1619 DelayOld(20), 1620 MoveUD(-0.333323), 1621 DelayOld(20), 1622 MoveUD(-0.32548), 1623 DelayOld(10), 1624 MoveUD(-0.30195), 1625 DelayOld(20), 1626 MoveUD(-0.27842), 1627 DelayOld(30), 1628 MoveUD(-0.254891), 1629 MoveUD(-0.231361), 1630 DelayOld(30), 1631 MoveUD(-0.207831), 1632 DelayOld(20), 1633 MoveUD(-0.199988), 1634 MoveUD(-0.176458), 1635 DelayOld(30), 1636 MoveUD(-0.137242), 1637 MoveUD(-0.0823389), 1638 DelayOld(20), 1639 MoveUD(-0.0274361), 1640 DelayOld(20), 1641 MoveUD(0.00393689), 1642 DelayOld(40), 1643 MoveUD(0.0353099), 1644 DelayOld(20), 1645 MoveUD(0.113742), 1646 DelayOld(10), 1647 MoveUD(0.137272), 1648 DelayOld(20), 1649 MoveUD(0.160802), 1650 MoveUD(0.184332), 1651 DelayOld(20), 1652 MoveUD(0.207862), 1653 DelayOld(30), 1654 MoveUD(0.247078), 1655 MoveUD(0.262764), 1656 DelayOld(20), 1657 MoveUD(0.270608), 1658 DelayOld(30), 1659 MoveUD(0.294137), 1660 MoveUD(0.32551), 1661 DelayOld(30), 1662 MoveUD(0.37257), 1663 Celebrate('left', 1), 1664 DelayOld(20), 1665 MoveUD(0.498062), 1666 MoveUD(0.560808), 1667 DelayOld(30), 1668 MoveUD(0.654927), 1669 MoveUD(0.694143), 1670 DelayOld(30), 1671 MoveUD(0.741203), 1672 DelayOld(20), 1673 MoveUD(0.780419), 1674 MoveUD(0.819636), 1675 DelayOld(20), 1676 MoveUD(0.843165), 1677 DelayOld(20), 1678 MoveUD(0.882382), 1679 DelayOld(10), 1680 MoveUD(0.913755), 1681 DelayOld(30), 1682 MoveUD(0.968657), 1683 MoveUD(1), 1684 DelayOld(560), 1685 Punch(release=False), 1686 DelayOld(210), 1687 MoveUD(0.968657), 1688 DelayOld(30), 1689 MoveUD(0.75689), 1690 PunchRelease(), 1691 DelayOld(20), 1692 MoveLR(0.95294), 1693 MoveUD(0.435316), 1694 RunRelease(), 1695 JumpRelease(), 1696 MoveLR(0.811762), 1697 MoveUD(0.270608), 1698 DelayOld(20), 1699 MoveLR(0.670583), 1700 MoveUD(0.160802), 1701 DelayOld(20), 1702 MoveLR(0.466659), 1703 MoveUD(0.0588397), 1704 DelayOld(10), 1705 MoveLR(0.317637), 1706 MoveUD(-0.00390637), 1707 DelayOld(20), 1708 MoveLR(0.0801416), 1709 DelayOld(10), 1710 MoveLR(0), 1711 DelayOld(20), 1712 MoveLR(0), 1713 DelayOld(30), 1714 MoveLR(0), 1715 DelayOld(30), 1716 MoveLR(0), 1717 DelayOld(20), 1718 MoveLR(0), 1719 DelayOld(100), 1720 MoveLR(0), 1721 DelayOld(30), 1722 MoveUD(0), 1723 DelayOld(30), 1724 MoveUD(0), 1725 DelayOld(50), 1726 MoveUD(0), 1727 MoveUD(0), 1728 DelayOld(30), 1729 MoveLR(0), 1730 MoveUD(-0.0520646), 1731 MoveLR(0), 1732 MoveUD(-0.0640889), 1733 DelayOld(20), 1734 MoveLR(0), 1735 MoveUD(-0.0881375), 1736 DelayOld(30), 1737 MoveLR(-0.0498978), 1738 MoveUD(-0.199988), 1739 MoveLR(-0.121586), 1740 MoveUD(-0.207831), 1741 DelayOld(20), 1742 MoveLR(-0.145116), 1743 MoveUD(-0.223518), 1744 DelayOld(30), 1745 MoveLR(-0.152959), 1746 MoveUD(-0.231361), 1747 MoveLR(-0.192175), 1748 MoveUD(-0.262734), 1749 DelayOld(30), 1750 MoveLR(-0.200018), 1751 MoveUD(-0.27842), 1752 DelayOld(20), 1753 MoveLR(-0.239235), 1754 MoveUD(-0.30195), 1755 MoveUD(-0.309793), 1756 DelayOld(40), 1757 MoveUD(-0.333323), 1758 DelayOld(10), 1759 MoveUD(-0.34901), 1760 DelayOld(30), 1761 MoveUD(-0.372539), 1762 MoveUD(-0.396069), 1763 DelayOld(20), 1764 MoveUD(-0.443129), 1765 DelayOld(20), 1766 MoveUD(-0.458815), 1767 DelayOld(10), 1768 MoveUD(-0.474502), 1769 DelayOld(50), 1770 MoveUD(-0.482345), 1771 DelayOld(30), 1772 MoveLR(-0.215705), 1773 DelayOld(30), 1774 MoveLR(-0.200018), 1775 DelayOld(10), 1776 MoveLR(-0.192175), 1777 DelayOld(10), 1778 MoveLR(-0.176489), 1779 DelayOld(30), 1780 MoveLR(-0.152959), 1781 DelayOld(20), 1782 MoveLR(-0.145116), 1783 MoveLR(-0.121586), 1784 MoveUD(-0.458815), 1785 DelayOld(30), 1786 MoveLR(-0.098056), 1787 MoveUD(-0.419599), 1788 DelayOld(10), 1789 MoveLR(-0.0745262), 1790 MoveUD(-0.333323), 1791 DelayOld(10), 1792 MoveLR(0.00390637), 1793 MoveUD(0), 1794 DelayOld(990), 1795 MoveLR(0), 1796 DelayOld(660), 1797 MoveUD(0), 1798 AnalyticsScreen('Tutorial Section 4'), 1799 Text( 1800 bs.Lstr(resource=f'{self._r}.phrase12Text') 1801 ), # for extra-awesome punches,... 1802 DelayOld(200), 1803 SpawnSpaz( 1804 0, 1805 ( 1806 2.368781805038452, 1807 4.337533950805664, 1808 -4.360159873962402, 1809 ), 1810 make_current=True, 1811 flash=False, 1812 ), 1813 SpawnSpaz( 1814 1, 1815 (-3.2, 4.3, -4.5), 1816 make_current=False, 1817 color=(1.0, 0.7, 0.3), 1818 # name=R.randomName3Text), 1819 name=bs.Lstr(resource=f'{self._r}.randomName3Text'), 1820 ), 1821 DelayOld(100), 1822 Powerup(1, (2.5, 0.0, 0), relative_to=0), 1823 Move(1, 0), 1824 DelayOld(1700), 1825 Move(0, -0.1), 1826 DelayOld(100), 1827 Move(0, 0), 1828 DelayOld(500), 1829 DelayOld(320), 1830 MoveLR(0), 1831 DelayOld(20), 1832 MoveLR(0), 1833 DelayOld(10), 1834 MoveLR(0), 1835 DelayOld(20), 1836 MoveLR(-0.333354), 1837 MoveLR(-0.592181), 1838 DelayOld(20), 1839 MoveLR(-0.788263), 1840 DelayOld(20), 1841 MoveLR(-1), 1842 MoveUD(0.0353099), 1843 MoveUD(0.0588397), 1844 DelayOld(10), 1845 Run(release=False), 1846 DelayOld(780), 1847 MoveUD(0.0274667), 1848 MoveUD(0.00393689), 1849 DelayOld(10), 1850 MoveUD(-0.00390637), 1851 DelayOld(440), 1852 MoveUD(0.0353099), 1853 DelayOld(20), 1854 MoveUD(0.0588397), 1855 DelayOld(10), 1856 MoveUD(0.0902127), 1857 DelayOld(260), 1858 MoveUD(0.0353099), 1859 DelayOld(30), 1860 MoveUD(0.00393689), 1861 DelayOld(10), 1862 MoveUD(-0.00390637), 1863 MoveUD(-0.0274361), 1864 Celebrate('left', 1), 1865 DelayOld(10), 1866 MoveUD(-0.0823389), 1867 DelayOld(30), 1868 MoveUD(-0.176458), 1869 MoveUD(-0.286264), 1870 DelayOld(20), 1871 MoveUD(-0.498032), 1872 Jump(release=False), 1873 MoveUD(-0.764702), 1874 DelayOld(30), 1875 MoveLR(-0.858852), 1876 MoveUD(-1), 1877 MoveLR(-0.780419), 1878 DelayOld(20), 1879 MoveLR(-0.717673), 1880 DelayOld(10), 1881 MoveLR(-0.552965), 1882 DelayOld(10), 1883 MoveLR(-0.341197), 1884 DelayOld(10), 1885 MoveLR(-0.0274667), 1886 DelayOld(10), 1887 MoveLR(0.27842), 1888 DelayOld(20), 1889 MoveLR(0.811762), 1890 MoveLR(1), 1891 RunRelease(), 1892 JumpRelease(), 1893 DelayOld(260), 1894 MoveLR(0.95294), 1895 DelayOld(30), 1896 MoveLR(0.756859), 1897 DelayOld(10), 1898 MoveLR(0.317637), 1899 MoveLR(-0.00393689), 1900 DelayOld(10), 1901 MoveLR(-0.341197), 1902 DelayOld(10), 1903 MoveLR(-0.647084), 1904 MoveUD(-0.921567), 1905 DelayOld(10), 1906 MoveLR(-1), 1907 MoveUD(-0.599994), 1908 MoveUD(-0.474502), 1909 DelayOld(10), 1910 MoveUD(-0.309793), 1911 DelayOld(10), 1912 MoveUD(-0.160772), 1913 MoveUD(-0.0352794), 1914 Delay(10), 1915 MoveUD(0.176489), 1916 Delay(10), 1917 MoveUD(0.607868), 1918 Run(release=False), 1919 Jump(release=False), 1920 DelayOld(20), 1921 MoveUD(1), 1922 DelayOld(30), 1923 MoveLR(-0.921598), 1924 DelayOld(10), 1925 Punch(release=False), 1926 MoveLR(-0.639241), 1927 DelayOld(10), 1928 MoveLR(-0.223548), 1929 DelayOld(10), 1930 MoveLR(0.254891), 1931 DelayOld(10), 1932 MoveLR(0.741172), 1933 MoveLR(1), 1934 DelayOld(40), 1935 JumpRelease(), 1936 DelayOld(40), 1937 MoveUD(0.976501), 1938 DelayOld(10), 1939 MoveUD(0.73336), 1940 DelayOld(10), 1941 MoveUD(0.309824), 1942 DelayOld(20), 1943 MoveUD(-0.184301), 1944 DelayOld(20), 1945 MoveUD(-0.811762), 1946 MoveUD(-1), 1947 KillSpaz(1, explode=True), 1948 DelayOld(10), 1949 RunRelease(), 1950 PunchRelease(), 1951 DelayOld(110), 1952 MoveLR(0.97647), 1953 MoveLR(0.898038), 1954 DelayOld(20), 1955 MoveLR(0.788232), 1956 DelayOld(20), 1957 MoveLR(0.670583), 1958 DelayOld(10), 1959 MoveLR(0.505875), 1960 DelayOld(10), 1961 MoveLR(0.32548), 1962 DelayOld(20), 1963 MoveLR(0.137242), 1964 DelayOld(10), 1965 MoveLR(-0.00393689), 1966 DelayOld(10), 1967 MoveLR(-0.215705), 1968 MoveLR(-0.356883), 1969 DelayOld(20), 1970 MoveLR(-0.451003), 1971 DelayOld(10), 1972 MoveLR(-0.552965), 1973 DelayOld(20), 1974 MoveLR(-0.670614), 1975 MoveLR(-0.780419), 1976 DelayOld(10), 1977 MoveLR(-0.898068), 1978 DelayOld(20), 1979 MoveLR(-1), 1980 DelayOld(370), 1981 MoveLR(-0.976501), 1982 DelayOld(10), 1983 MoveLR(-0.952971), 1984 DelayOld(10), 1985 MoveLR(-0.929441), 1986 MoveLR(-0.898068), 1987 DelayOld(30), 1988 MoveLR(-0.874538), 1989 DelayOld(10), 1990 MoveLR(-0.851009), 1991 DelayOld(10), 1992 MoveLR(-0.835322), 1993 MoveUD(-0.968627), 1994 DelayOld(10), 1995 MoveLR(-0.827479), 1996 MoveUD(-0.960784), 1997 DelayOld(20), 1998 MoveUD(-0.945097), 1999 DelayOld(70), 2000 MoveUD(-0.937254), 2001 DelayOld(20), 2002 MoveUD(-0.913724), 2003 DelayOld(20), 2004 MoveUD(-0.890194), 2005 MoveLR(-0.780419), 2006 MoveUD(-0.827448), 2007 DelayOld(20), 2008 MoveLR(0.317637), 2009 MoveUD(0.3961), 2010 MoveLR(0.0195929), 2011 MoveUD(0.056093), 2012 DelayOld(20), 2013 MoveUD(0), 2014 DelayOld(750), 2015 MoveLR(0), 2016 Text( 2017 bs.Lstr( 2018 resource=f'{self._r}.phrase13Text', 2019 subs=[ 2020 ( 2021 '${NAME}', 2022 bs.Lstr( 2023 resource=f'{self._r}.randomName3Text' 2024 ), 2025 ) 2026 ], 2027 ) 2028 ), # whoops sorry bill 2029 RemoveGloves(), 2030 DelayOld(2000), 2031 AnalyticsScreen('Tutorial Section 5'), 2032 Text( 2033 bs.Lstr( 2034 resource=f'{self._r}.phrase14Text', 2035 subs=[ 2036 ( 2037 '${NAME}', 2038 bs.Lstr( 2039 resource=f'{self._r}.randomName4Text' 2040 ), 2041 ) 2042 ], 2043 ) 2044 ), # you can pick up and throw things such as chuck here 2045 SpawnSpaz( 2046 0, 2047 (-4.0, 4.3, -2.5), 2048 make_current=True, 2049 flash=False, 2050 angle=90, 2051 ), 2052 SpawnSpaz( 2053 1, 2054 (5, 0, -1.0), 2055 relative_to=0, 2056 make_current=False, 2057 color=(0.4, 1.0, 0.7), 2058 name=bs.Lstr(resource=f'{self._r}.randomName4Text'), 2059 ), 2060 DelayOld(1000), 2061 Celebrate('left', 1, duration=1000), 2062 Move(1, 0.2), 2063 DelayOld(2000), 2064 PickUp(), 2065 DelayOld(200), 2066 Move(0.5, 1.0), 2067 DelayOld(1200), 2068 PickUp(), 2069 Move(0, 0), 2070 DelayOld(1000), 2071 Celebrate('left'), 2072 DelayOld(1500), 2073 Move(0, -1.0), 2074 DelayOld(800), 2075 Move(0, 0), 2076 DelayOld(800), 2077 SpawnSpaz( 2078 0, 2079 (1.5, 4.3, -4.0), 2080 make_current=True, 2081 flash=False, 2082 angle=0, 2083 ), 2084 AnalyticsScreen('Tutorial Section 6'), 2085 Text( 2086 bs.Lstr(resource=f'{self._r}.phrase15Text') 2087 ), # lastly there's bombs 2088 DelayOld(1900), 2089 Text( 2090 bs.Lstr(resource=f'{self._r}.phrase16Text') 2091 ), # throwing bombs takes practice 2092 DelayOld(2000), 2093 Bomb(), 2094 Move(-0.1, -0.1), 2095 DelayOld(100), 2096 Move(0, 0), 2097 DelayOld(500), 2098 DelayOld(1000), 2099 Bomb(), 2100 DelayOld(2000), 2101 Text( 2102 bs.Lstr(resource=f'{self._r}.phrase17Text') 2103 ), # not a very good throw 2104 DelayOld(3000), 2105 Text( 2106 bs.Lstr(resource=f'{self._r}.phrase18Text') 2107 ), # moving helps you get distance 2108 DelayOld(1000), 2109 Bomb(), 2110 DelayOld(500), 2111 Move(-0.3, 0), 2112 DelayOld(100), 2113 Move(-0.6, 0), 2114 DelayOld(100), 2115 Move(-1, 0), 2116 DelayOld(800), 2117 Bomb(), 2118 DelayOld(400), 2119 Move(0, -0.1), 2120 DelayOld(100), 2121 Move(0, 0), 2122 DelayOld(2500), 2123 Text( 2124 bs.Lstr(resource=f'{self._r}.phrase19Text') 2125 ), # jumping helps you get height 2126 DelayOld(2000), 2127 Bomb(), 2128 DelayOld(500), 2129 Move(1, 0), 2130 DelayOld(300), 2131 Jump(release_delay=250), 2132 DelayOld(500), 2133 Jump(release_delay=250), 2134 DelayOld(550), 2135 Jump(release_delay=250), 2136 DelayOld(160), 2137 Punch(), 2138 DelayOld(500), 2139 Move(0, -0.1), 2140 DelayOld(100), 2141 Move(0, 0), 2142 DelayOld(2000), 2143 Text( 2144 bs.Lstr(resource=f'{self._r}.phrase20Text') 2145 ), # whiplash your bombs 2146 DelayOld(1000), 2147 Bomb(release=False), 2148 DelayOld2(80), 2149 RunRelease(), 2150 BombRelease(), 2151 DelayOld2(620), 2152 MoveLR(0), 2153 DelayOld2(10), 2154 MoveLR(0), 2155 DelayOld2(40), 2156 MoveLR(0), 2157 DelayOld2(10), 2158 MoveLR(-0.0537431), 2159 MoveUD(0), 2160 DelayOld2(20), 2161 MoveLR(-0.262764), 2162 DelayOld2(20), 2163 MoveLR(-0.498062), 2164 DelayOld2(10), 2165 MoveLR(-0.639241), 2166 DelayOld2(20), 2167 MoveLR(-0.73336), 2168 DelayOld2(10), 2169 MoveLR(-0.843165), 2170 MoveUD(-0.0352794), 2171 DelayOld2(30), 2172 MoveLR(-1), 2173 DelayOld2(10), 2174 MoveUD(-0.0588092), 2175 DelayOld2(10), 2176 MoveUD(-0.160772), 2177 DelayOld2(20), 2178 MoveUD(-0.286264), 2179 DelayOld2(20), 2180 MoveUD(-0.427442), 2181 DelayOld2(10), 2182 MoveUD(-0.623524), 2183 DelayOld2(20), 2184 MoveUD(-0.843135), 2185 DelayOld2(10), 2186 MoveUD(-1), 2187 DelayOld2(40), 2188 MoveLR(-0.890225), 2189 DelayOld2(10), 2190 MoveLR(-0.670614), 2191 DelayOld2(20), 2192 MoveLR(-0.435316), 2193 DelayOld2(20), 2194 MoveLR(-0.184332), 2195 DelayOld2(10), 2196 MoveLR(0.00390637), 2197 DelayOld2(20), 2198 MoveLR(0.223518), 2199 DelayOld2(10), 2200 MoveLR(0.388226), 2201 DelayOld2(20), 2202 MoveLR(0.560778), 2203 DelayOld2(20), 2204 MoveLR(0.717643), 2205 DelayOld2(10), 2206 MoveLR(0.890194), 2207 DelayOld2(20), 2208 MoveLR(1), 2209 DelayOld2(30), 2210 MoveUD(-0.968627), 2211 DelayOld2(20), 2212 MoveUD(-0.898038), 2213 DelayOld2(10), 2214 MoveUD(-0.741172), 2215 DelayOld2(20), 2216 MoveUD(-0.498032), 2217 DelayOld2(20), 2218 MoveUD(-0.247047), 2219 DelayOld2(10), 2220 MoveUD(0.00393689), 2221 DelayOld2(20), 2222 MoveUD(0.239235), 2223 DelayOld2(20), 2224 MoveUD(0.458846), 2225 DelayOld2(10), 2226 MoveUD(0.70983), 2227 DelayOld2(30), 2228 MoveUD(1), 2229 DelayOld2(10), 2230 MoveLR(0.827448), 2231 DelayOld2(10), 2232 MoveLR(0.678426), 2233 DelayOld2(20), 2234 MoveLR(0.396069), 2235 DelayOld2(10), 2236 MoveLR(0.0980255), 2237 DelayOld2(20), 2238 MoveLR(-0.160802), 2239 DelayOld2(20), 2240 MoveLR(-0.388256), 2241 DelayOld2(10), 2242 MoveLR(-0.545122), 2243 DelayOld2(30), 2244 MoveLR(-0.73336), 2245 DelayOld2(10), 2246 MoveLR(-0.945128), 2247 DelayOld2(10), 2248 MoveLR(-1), 2249 DelayOld2(50), 2250 MoveUD(0.960814), 2251 DelayOld2(20), 2252 MoveUD(0.890225), 2253 DelayOld2(10), 2254 MoveUD(0.749046), 2255 DelayOld2(20), 2256 MoveUD(0.623554), 2257 DelayOld2(20), 2258 MoveUD(0.498062), 2259 DelayOld2(10), 2260 MoveUD(0.34904), 2261 DelayOld2(20), 2262 MoveUD(0.239235), 2263 DelayOld2(20), 2264 MoveUD(0.137272), 2265 DelayOld2(10), 2266 MoveUD(0.0117801), 2267 DelayOld2(20), 2268 MoveUD(-0.0117496), 2269 DelayOld2(10), 2270 MoveUD(-0.0274361), 2271 DelayOld2(90), 2272 MoveUD(-0.0352794), 2273 Run(release=False), 2274 Jump(release=False), 2275 Delay(80), 2276 Punch(release=False), 2277 DelayOld2(60), 2278 MoveLR(-0.968657), 2279 DelayOld2(20), 2280 MoveLR(-0.835322), 2281 DelayOld2(10), 2282 MoveLR(-0.70983), 2283 JumpRelease(), 2284 DelayOld2(30), 2285 MoveLR(-0.592181), 2286 MoveUD(-0.0588092), 2287 DelayOld2(10), 2288 MoveLR(-0.490219), 2289 MoveUD(-0.0744957), 2290 DelayOld2(10), 2291 MoveLR(-0.41963), 2292 DelayOld2(20), 2293 MoveLR(0), 2294 MoveUD(0), 2295 DelayOld2(20), 2296 MoveUD(0), 2297 PunchRelease(), 2298 RunRelease(), 2299 DelayOld(500), 2300 Move(0, -0.1), 2301 DelayOld(100), 2302 Move(0, 0), 2303 DelayOld(2000), 2304 AnalyticsScreen('Tutorial Section 7'), 2305 Text( 2306 bs.Lstr(resource=f'{self._r}.phrase21Text') 2307 ), # timing your bombs can be tricky 2308 Move(-1, 0), 2309 DelayOld(1000), 2310 Move(0, -0.1), 2311 DelayOld(100), 2312 Move(0, 0), 2313 SpawnSpaz( 2314 0, 2315 (-0.7, 4.3, -3.9), 2316 make_current=True, 2317 flash=False, 2318 angle=-30, 2319 ), 2320 SpawnSpaz( 2321 1, 2322 (6.5, 0, -0.75), 2323 relative_to=0, 2324 make_current=False, 2325 color=(0.3, 0.8, 1.0), 2326 name=bs.Lstr(resource=f'{self._r}.randomName5Text'), 2327 ), 2328 DelayOld2(1000), 2329 Move(-1, 0), 2330 DelayOld2(1800), 2331 Bomb(), 2332 Move(0, 0), 2333 DelayOld2(300), 2334 Move(1, 0), 2335 DelayOld2(600), 2336 Jump(), 2337 DelayOld2(150), 2338 Punch(), 2339 DelayOld2(800), 2340 Move(-1, 0), 2341 DelayOld2(1000), 2342 Move(0, 0), 2343 DelayOld2(1500), 2344 Text(bs.Lstr(resource=f'{self._r}.phrase22Text')), # dang 2345 Delay(1500), 2346 Text(''), 2347 Delay(200), 2348 Text( 2349 bs.Lstr(resource=f'{self._r}.phrase23Text') 2350 ), # try cooking off 2351 Delay(1500), 2352 Bomb(), 2353 Delay(800), 2354 Move(1, 0.12), 2355 Delay(1100), 2356 Jump(), 2357 Delay(100), 2358 Punch(), 2359 Delay(100), 2360 Move(0, -0.1), 2361 Delay(100), 2362 Move(0, 0), 2363 Delay(2000), 2364 Text( 2365 bs.Lstr(resource=f'{self._r}.phrase24Text') 2366 ), # hooray nicely cooked 2367 Celebrate(), 2368 DelayOld(2000), 2369 KillSpaz(1), 2370 Text(''), 2371 Move(0.5, -0.5), 2372 DelayOld(1000), 2373 Move(0, -0.1), 2374 DelayOld(100), 2375 Move(0, 0), 2376 DelayOld(1000), 2377 AnalyticsScreen('Tutorial Section 8'), 2378 Text( 2379 bs.Lstr(resource=f'{self._r}.phrase25Text') 2380 ), # well that's just about it 2381 DelayOld(2000), 2382 Text( 2383 bs.Lstr(resource=f'{self._r}.phrase26Text') 2384 ), # go get em tiger 2385 DelayOld(2000), 2386 Text( 2387 bs.Lstr(resource=f'{self._r}.phrase27Text') 2388 ), # remember you training 2389 DelayOld(3000), 2390 Text( 2391 bs.Lstr(resource=f'{self._r}.phrase28Text') 2392 ), # well maybe 2393 DelayOld(1600), 2394 Text( 2395 bs.Lstr(resource=f'{self._r}.phrase29Text') 2396 ), # good luck 2397 Celebrate('right', duration=10000), 2398 DelayOld(1000), 2399 AnalyticsScreen('Tutorial Complete'), 2400 End(), 2401 ] 2402 ) 2403 2404 except Exception: 2405 logging.exception('Error running tutorial.') 2406 2407 # If we read some, exec them. 2408 if self._entries: 2409 self._run_next_entry() 2410 # Otherwise try again in a few seconds. 2411 else: 2412 self._read_entries_timer = bs.Timer( 2413 3.0, bs.WeakCall(self._read_entries) 2414 ) 2415 2416 def _run_next_entry(self) -> None: 2417 while self._entries: 2418 entry = self._entries.popleft() 2419 try: 2420 result = entry.run(self) 2421 except Exception: 2422 result = None 2423 logging.exception('Error in tutorial _run_next_entry.') 2424 2425 # If the entry returns an int value, set a timer; 2426 # otherwise just keep going. 2427 if result is not None: 2428 self._entry_timer = bs.Timer( 2429 result / 1000.0, bs.WeakCall(self._run_next_entry) 2430 ) 2431 return 2432 2433 # Done with these entries.. start over soon. 2434 self._read_entries_timer = bs.Timer( 2435 1.0, bs.WeakCall(self._read_entries) 2436 ) 2437 2438 def _update_skip_votes(self) -> None: 2439 count = sum(1 for player in self.players if player.pressed) 2440 assert self._skip_count_text 2441 self._skip_count_text.text = ( 2442 bs.Lstr( 2443 resource=f'{self._r}.skipVoteCountText', 2444 subs=[ 2445 ('${COUNT}', str(count)), 2446 ('${TOTAL}', str(len(self.players))), 2447 ], 2448 ) 2449 if count > 0 2450 else '' 2451 ) 2452 if ( 2453 count >= len(self.players) 2454 and self.players 2455 and not self._have_skipped 2456 ): 2457 bs.increment_analytics_count('Tutorial skip') 2458 bs.set_analytics_screen('Tutorial Skip') 2459 self._have_skipped = True 2460 bs.getsound('swish').play() 2461 # self._skip_count_text.text = self._r.skippingText 2462 self._skip_count_text.text = bs.Lstr( 2463 resource=f'{self._r}.skippingText' 2464 ) 2465 assert self._skip_text 2466 self._skip_text.text = '' 2467 self.end() 2468 2469 def _player_pressed_button(self, player: Player) -> None: 2470 # Special case: if there's only one player, we give them a 2471 # warning on their first press (some players were thinking the 2472 # on-screen guide meant they were supposed to press something). 2473 if len(self.players) == 1 and not self._issued_warning: 2474 self._issued_warning = True 2475 assert self._skip_text 2476 self._skip_text.text = bs.Lstr( 2477 resource=f'{self._r}.skipConfirmText' 2478 ) 2479 self._skip_text.color = (1, 1, 1) 2480 self._skip_text.scale = 1.3 2481 incr = 50 2482 t = incr 2483 for _i in range(6): 2484 bs.timer( 2485 t / 1000.0, 2486 bs.Call(setattr, self._skip_text, 'color', (1, 0.5, 0.1)), 2487 ) 2488 t += incr 2489 bs.timer( 2490 t / 1000.0, 2491 bs.Call(setattr, self._skip_text, 'color', (1, 1, 0)), 2492 ) 2493 t += incr 2494 bs.timer(6.0, bs.WeakCall(self._revert_confirm)) 2495 return 2496 2497 player.pressed = True 2498 2499 # test... 2500 if not all(self.players): 2501 logging.error( 2502 'Nonexistent player in _player_pressed_button:' 2503 ' %s: we are %s', 2504 [str(p) for p in self.players], 2505 player, 2506 ) 2507 2508 self._update_skip_votes() 2509 2510 def _revert_confirm(self) -> None: 2511 assert self._skip_text 2512 self._skip_text.text = bs.Lstr( 2513 resource=f'{self._r}.toSkipPressAnythingText' 2514 ) 2515 self._skip_text.color = (1, 1, 1) 2516 self._issued_warning = False 2517 2518 @override 2519 def on_player_join(self, player: Player) -> None: 2520 super().on_player_join(player) 2521 2522 # We just wanna know if this player presses anything. 2523 player.assigninput( 2524 ( 2525 bs.InputType.JUMP_PRESS, 2526 bs.InputType.PUNCH_PRESS, 2527 bs.InputType.BOMB_PRESS, 2528 bs.InputType.PICK_UP_PRESS, 2529 ), 2530 bs.Call(self._player_pressed_button, player), 2531 ) 2532 2533 @override 2534 def on_player_leave(self, player: Player) -> None: 2535 if not all(self.players): 2536 logging.error( 2537 'Nonexistent player in on_player_leave: %s: we are %s', 2538 [str(p) for p in self.players], 2539 player, 2540 ) 2541 super().on_player_leave(player) 2542 # our leaving may influence the vote total needed/etc 2543 self._update_skip_votes()
36class ButtonPress: 37 def __init__( 38 self, 39 button: str, 40 delay: int = 0, 41 release: bool = True, 42 release_delay: int = 0, 43 ): 44 self._button = button 45 self._delay = delay 46 self._release = release 47 self._release_delay = release_delay 48 49 def run(self, a: TutorialActivity) -> None: 50 s = a.current_spaz 51 assert s is not None 52 img: bs.Node | None 53 release_call: Callable[[], None] | None 54 color: Sequence[float] | None 55 if self._button == 'punch': 56 call = s.on_punch_press 57 release_call = s.on_punch_release 58 img = a.punch_image 59 color = a.punch_image_color 60 elif self._button == 'jump': 61 call = s.on_jump_press 62 release_call = s.on_jump_release 63 img = a.jump_image 64 color = a.jump_image_color 65 elif self._button == 'bomb': 66 call = s.on_bomb_press 67 release_call = s.on_bomb_release 68 img = a.bomb_image 69 color = a.bomb_image_color 70 elif self._button == 'pickUp': 71 call = s.on_pickup_press 72 release_call = s.on_pickup_release 73 img = a.pickup_image 74 color = a.pickup_image_color 75 elif self._button == 'run': 76 call = bs.Call(s.on_run, 1.0) 77 release_call = bs.Call(s.on_run, 0.0) 78 img = None 79 color = None 80 else: 81 raise RuntimeError(f'invalid button: {self._button}') 82 83 brightness = 4.0 84 if color is not None: 85 c_bright = list(color) 86 c_bright[0] *= brightness 87 c_bright[1] *= brightness 88 c_bright[2] *= brightness 89 else: 90 c_bright = [1.0, 1.0, 1.0] 91 92 if self._delay == 0: 93 call() 94 if img is not None: 95 img.color = c_bright 96 img.vr_depth = -40 97 else: 98 bs.timer(self._delay / 1000.0, call) 99 if img is not None: 100 bs.timer( 101 self._delay / 1000.0, 102 bs.Call(_safesetattr, img, 'color', c_bright), 103 ) 104 bs.timer( 105 self._delay / 1000.0, 106 bs.Call(_safesetattr, img, 'vr_depth', -30), 107 ) 108 if self._release: 109 if self._delay == 0 and self._release_delay == 0: 110 release_call() 111 else: 112 bs.timer( 113 0.001 * (self._delay + self._release_delay), release_call 114 ) 115 if img is not None: 116 bs.timer( 117 (self._delay + self._release_delay + 100) / 1000.0, 118 bs.Call(_safesetattr, img, 'color', color), 119 ) 120 bs.timer( 121 (self._delay + self._release_delay + 100) / 1000.0, 122 bs.Call(_safesetattr, img, 'vr_depth', -20), 123 )
49 def run(self, a: TutorialActivity) -> None: 50 s = a.current_spaz 51 assert s is not None 52 img: bs.Node | None 53 release_call: Callable[[], None] | None 54 color: Sequence[float] | None 55 if self._button == 'punch': 56 call = s.on_punch_press 57 release_call = s.on_punch_release 58 img = a.punch_image 59 color = a.punch_image_color 60 elif self._button == 'jump': 61 call = s.on_jump_press 62 release_call = s.on_jump_release 63 img = a.jump_image 64 color = a.jump_image_color 65 elif self._button == 'bomb': 66 call = s.on_bomb_press 67 release_call = s.on_bomb_release 68 img = a.bomb_image 69 color = a.bomb_image_color 70 elif self._button == 'pickUp': 71 call = s.on_pickup_press 72 release_call = s.on_pickup_release 73 img = a.pickup_image 74 color = a.pickup_image_color 75 elif self._button == 'run': 76 call = bs.Call(s.on_run, 1.0) 77 release_call = bs.Call(s.on_run, 0.0) 78 img = None 79 color = None 80 else: 81 raise RuntimeError(f'invalid button: {self._button}') 82 83 brightness = 4.0 84 if color is not None: 85 c_bright = list(color) 86 c_bright[0] *= brightness 87 c_bright[1] *= brightness 88 c_bright[2] *= brightness 89 else: 90 c_bright = [1.0, 1.0, 1.0] 91 92 if self._delay == 0: 93 call() 94 if img is not None: 95 img.color = c_bright 96 img.vr_depth = -40 97 else: 98 bs.timer(self._delay / 1000.0, call) 99 if img is not None: 100 bs.timer( 101 self._delay / 1000.0, 102 bs.Call(_safesetattr, img, 'color', c_bright), 103 ) 104 bs.timer( 105 self._delay / 1000.0, 106 bs.Call(_safesetattr, img, 'vr_depth', -30), 107 ) 108 if self._release: 109 if self._delay == 0 and self._release_delay == 0: 110 release_call() 111 else: 112 bs.timer( 113 0.001 * (self._delay + self._release_delay), release_call 114 ) 115 if img is not None: 116 bs.timer( 117 (self._delay + self._release_delay + 100) / 1000.0, 118 bs.Call(_safesetattr, img, 'color', color), 119 ) 120 bs.timer( 121 (self._delay + self._release_delay + 100) / 1000.0, 122 bs.Call(_safesetattr, img, 'vr_depth', -20), 123 )
126class ButtonRelease: 127 def __init__(self, button: str, delay: int = 0): 128 self._button = button 129 self._delay = delay 130 131 def run(self, a: TutorialActivity) -> None: 132 s = a.current_spaz 133 assert s is not None 134 call: Callable[[], None] | None 135 img: bs.Node | None 136 color: Sequence[float] | None 137 if self._button == 'punch': 138 call = s.on_punch_release 139 img = a.punch_image 140 color = a.punch_image_color 141 elif self._button == 'jump': 142 call = s.on_jump_release 143 img = a.jump_image 144 color = a.jump_image_color 145 elif self._button == 'bomb': 146 call = s.on_bomb_release 147 img = a.bomb_image 148 color = a.bomb_image_color 149 elif self._button == 'pickUp': 150 call = s.on_pickup_press 151 img = a.pickup_image 152 color = a.pickup_image_color 153 elif self._button == 'run': 154 call = bs.Call(s.on_run, 0.0) 155 img = None 156 color = None 157 else: 158 raise RuntimeError('invalid button: ' + self._button) 159 if self._delay == 0: 160 call() 161 else: 162 bs.timer(self._delay / 1000.0, call) 163 if img is not None: 164 bs.timer( 165 (self._delay + 100) / 1000.0, 166 bs.Call(_safesetattr, img, 'color', color), 167 ) 168 bs.timer( 169 (self._delay + 100 / 1000.0), 170 bs.Call(_safesetattr, img, 'vr_depth', -20), 171 )
131 def run(self, a: TutorialActivity) -> None: 132 s = a.current_spaz 133 assert s is not None 134 call: Callable[[], None] | None 135 img: bs.Node | None 136 color: Sequence[float] | None 137 if self._button == 'punch': 138 call = s.on_punch_release 139 img = a.punch_image 140 color = a.punch_image_color 141 elif self._button == 'jump': 142 call = s.on_jump_release 143 img = a.jump_image 144 color = a.jump_image_color 145 elif self._button == 'bomb': 146 call = s.on_bomb_release 147 img = a.bomb_image 148 color = a.bomb_image_color 149 elif self._button == 'pickUp': 150 call = s.on_pickup_press 151 img = a.pickup_image 152 color = a.pickup_image_color 153 elif self._button == 'run': 154 call = bs.Call(s.on_run, 0.0) 155 img = None 156 color = None 157 else: 158 raise RuntimeError('invalid button: ' + self._button) 159 if self._delay == 0: 160 call() 161 else: 162 bs.timer(self._delay / 1000.0, call) 163 if img is not None: 164 bs.timer( 165 (self._delay + 100) / 1000.0, 166 bs.Call(_safesetattr, img, 'color', color), 167 ) 168 bs.timer( 169 (self._delay + 100 / 1000.0), 170 bs.Call(_safesetattr, img, 'vr_depth', -20), 171 )
174class Player(bs.Player['Team']): 175 """Our player type for this game.""" 176 177 def __init__(self) -> None: 178 self.pressed = False
Our player type for this game.
Inherited Members
- bascenev1._player.Player
- character
- actor
- color
- highlight
- on_expire
- team
- customdata
- sessionplayer
- node
- position
- exists
- getname
- is_alive
- get_icon
- assigninput
- resetinput
181class Team(bs.Team[Player]): 182 """Our team type for this game.""" 183 184 def __init__(self) -> None: 185 pass
Our team type for this game.
Inherited Members
- bascenev1._team.Team
- players
- id
- name
- color
- manual_init
- customdata
- on_expire
- sessionteam
188class TutorialActivity(bs.Activity[Player, Team]): 189 def __init__(self, settings: dict | None = None): 190 from bascenev1lib.maps import Rampage 191 192 if settings is None: 193 settings = {} 194 super().__init__(settings) 195 self.current_spaz: Spaz | None = None 196 self._benchmark_type = getattr(bs.getsession(), 'benchmark_type', None) 197 self.last_start_time: int | None = None 198 self.cycle_times: list[int] = [] 199 self.allow_pausing = True 200 self.allow_kick_idle_players = False 201 self._issued_warning = False 202 self._map_type = Rampage 203 self._map_type.preload() 204 self._jump_button_tex = bs.gettexture('buttonJump') 205 self._pick_up_button_tex = bs.gettexture('buttonPickUp') 206 self._bomb_button_tex = bs.gettexture('buttonBomb') 207 self._punch_button_tex = bs.gettexture('buttonPunch') 208 self._r = 'tutorial' 209 self._have_skipped = False 210 self.stick_image_position_x = self.stick_image_position_y = 0.0 211 self.spawn_sound = bs.getsound('spawn') 212 self.map: bs.Map | None = None 213 self.text: bs.Node | None = None 214 self._skip_text: bs.Node | None = None 215 self._skip_count_text: bs.Node | None = None 216 self._scale: float | None = None 217 self._stick_base_position: tuple[float, float] = (0.0, 0.0) 218 self._stick_nub_position: tuple[float, float] = (0.0, 0.0) 219 self._stick_base_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 220 self._stick_nub_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 221 self._time: int = -1 222 self.punch_image_color = (1.0, 1.0, 1.0) 223 self.punch_image: bs.Node | None = None 224 self.bomb_image: bs.Node | None = None 225 self.jump_image: bs.Node | None = None 226 self.pickup_image: bs.Node | None = None 227 self._stick_base_image: bs.Node | None = None 228 self._stick_nub_image: bs.Node | None = None 229 self.bomb_image_color = (1.0, 1.0, 1.0) 230 self.pickup_image_color = (1.0, 1.0, 1.0) 231 self.control_ui_nodes: list[bs.Node] = [] 232 self.spazzes: dict[int, Spaz] = {} 233 self.jump_image_color = (1.0, 1.0, 1.0) 234 self._entries: deque[Any] = deque() 235 self._read_entries_timer: bs.Timer | None = None 236 self._entry_timer: bs.Timer | None = None 237 238 @override 239 def on_transition_in(self) -> None: 240 super().on_transition_in() 241 bs.setmusic(bs.MusicType.CHAR_SELECT, continuous=True) 242 self.map = self._map_type() 243 244 @override 245 def on_begin(self) -> None: 246 super().on_begin() 247 248 bs.set_analytics_screen('Tutorial Start') 249 bs.increment_analytics_count('Tutorial start') 250 251 if bool(False): 252 # Buttons on top. 253 text_y = 140 254 buttons_y = 250 255 else: 256 # Buttons on bottom. 257 text_y = 260 258 buttons_y = 160 259 260 # Need different versions of this: taps/buttons/keys. 261 self.text = bs.newnode( 262 'text', 263 attrs={ 264 'text': '', 265 'scale': 1.9, 266 'position': (0, text_y), 267 'maxwidth': 500, 268 'flatness': 0.0, 269 'shadow': 0.5, 270 'h_align': 'center', 271 'v_align': 'center', 272 'v_attach': 'center', 273 }, 274 ) 275 276 # Need different versions of this: taps/buttons/keys. 277 txt = ( 278 bs.Lstr(resource=f'{self._r}.cpuBenchmarkText') 279 if self._benchmark_type == 'cpu' 280 else bs.Lstr(resource=f'{self._r}.toSkipPressAnythingText') 281 ) 282 t = self._skip_text = bs.newnode( 283 'text', 284 attrs={ 285 'text': txt, 286 'maxwidth': 900, 287 'scale': 1.1, 288 'vr_depth': 100, 289 'position': (0, 30), 290 'h_align': 'center', 291 'v_align': 'center', 292 'v_attach': 'bottom', 293 }, 294 ) 295 bs.animate(t, 'opacity', {1.0: 0.0, 2.0: 0.7}) 296 self._skip_count_text = bs.newnode( 297 'text', 298 attrs={ 299 'text': '', 300 'scale': 1.4, 301 'vr_depth': 90, 302 'position': (0, 70), 303 'h_align': 'center', 304 'v_align': 'center', 305 'v_attach': 'bottom', 306 }, 307 ) 308 309 ouya = False 310 311 self._scale = scale = 0.6 312 center_offs = 130.0 * scale 313 offs = 65.0 * scale 314 position = (0, buttons_y) 315 image_size = 90.0 * scale 316 image_size_2 = 220.0 * scale 317 nub_size = 110.0 * scale 318 p = (position[0] + center_offs, position[1] - offs) 319 320 def _sc(r: float, g: float, b: float) -> tuple[float, float, float]: 321 return 0.6 * r, 0.6 * g, 0.6 * b 322 323 self.jump_image_color = c = _sc(0.4, 1, 0.4) 324 self.jump_image = bs.newnode( 325 'image', 326 attrs={ 327 'texture': self._jump_button_tex, 328 'absolute_scale': True, 329 'vr_depth': -20, 330 'position': p, 331 'scale': (image_size, image_size), 332 'color': c, 333 }, 334 ) 335 p = (position[0] + center_offs - offs, position[1]) 336 self.punch_image_color = c = ( 337 _sc(0.2, 0.6, 1) if ouya else _sc(1, 0.7, 0.3) 338 ) 339 self.punch_image = bs.newnode( 340 'image', 341 attrs={ 342 'texture': bs.gettexture('buttonPunch'), 343 'absolute_scale': True, 344 'vr_depth': -20, 345 'position': p, 346 'scale': (image_size, image_size), 347 'color': c, 348 }, 349 ) 350 p = (position[0] + center_offs + offs, position[1]) 351 self.bomb_image_color = c = _sc(1, 0.3, 0.3) 352 self.bomb_image = bs.newnode( 353 'image', 354 attrs={ 355 'texture': bs.gettexture('buttonBomb'), 356 'absolute_scale': True, 357 'vr_depth': -20, 358 'position': p, 359 'scale': (image_size, image_size), 360 'color': c, 361 }, 362 ) 363 p = (position[0] + center_offs, position[1] + offs) 364 self.pickup_image_color = c = ( 365 _sc(1, 0.8, 0.3) if ouya else _sc(0.5, 0.5, 1) 366 ) 367 self.pickup_image = bs.newnode( 368 'image', 369 attrs={ 370 'texture': bs.gettexture('buttonPickUp'), 371 'absolute_scale': True, 372 'vr_depth': -20, 373 'position': p, 374 'scale': (image_size, image_size), 375 'color': c, 376 }, 377 ) 378 379 self._stick_base_position = p = (position[0] - center_offs, position[1]) 380 self._stick_base_image_color = c2 = (0.25, 0.25, 0.25, 1.0) 381 self._stick_base_image = bs.newnode( 382 'image', 383 attrs={ 384 'texture': bs.gettexture('nub'), 385 'absolute_scale': True, 386 'vr_depth': -40, 387 'position': p, 388 'scale': (image_size_2, image_size_2), 389 'color': c2, 390 }, 391 ) 392 self._stick_nub_position = p = (position[0] - center_offs, position[1]) 393 self._stick_nub_image_color = c3 = (0.4, 0.4, 0.4, 1.0) 394 self._stick_nub_image = bs.newnode( 395 'image', 396 attrs={ 397 'texture': bs.gettexture('nub'), 398 'absolute_scale': True, 399 'position': p, 400 'scale': (nub_size, nub_size), 401 'color': c3, 402 }, 403 ) 404 self.control_ui_nodes = [ 405 self.jump_image, 406 self.punch_image, 407 self.bomb_image, 408 self.pickup_image, 409 self._stick_base_image, 410 self._stick_nub_image, 411 ] 412 for n in self.control_ui_nodes: 413 n.opacity = 0.0 414 self._read_entries() 415 416 def set_stick_image_position(self, x: float, y: float) -> None: 417 # Clamp this to a circle. 418 len_squared = x * x + y * y 419 if len_squared > 1.0: 420 length = math.sqrt(len_squared) 421 mult = 1.0 / length 422 x *= mult 423 y *= mult 424 425 self.stick_image_position_x = x 426 self.stick_image_position_y = y 427 offs = 50.0 428 assert self._scale is not None 429 p = [ 430 self._stick_nub_position[0] + x * offs * self._scale, 431 self._stick_nub_position[1] + y * offs * self._scale, 432 ] 433 c = list(self._stick_nub_image_color) 434 if abs(x) > 0.1 or abs(y) > 0.1: 435 c[0] *= 2.0 436 c[1] *= 4.0 437 c[2] *= 2.0 438 assert self._stick_nub_image is not None 439 self._stick_nub_image.position = p 440 self._stick_nub_image.color = c 441 c = list(self._stick_base_image_color) 442 if abs(x) > 0.1 or abs(y) > 0.1: 443 c[0] *= 1.5 444 c[1] *= 1.5 445 c[2] *= 1.5 446 assert self._stick_base_image is not None 447 self._stick_base_image.color = c 448 449 def _read_entries(self) -> None: 450 try: 451 452 class Reset: 453 def __init__(self) -> None: 454 pass 455 456 def run(self, a: TutorialActivity) -> None: 457 # if we're looping, print out how long each cycle took 458 # print out how long each cycle took.. 459 if a.last_start_time is not None: 460 tval = int(bs.apptime() * 1000.0) - a.last_start_time 461 assert isinstance(tval, int) 462 diff = tval 463 a.cycle_times.append(diff) 464 bs.broadcastmessage( 465 'cycle time: ' 466 + str(diff) 467 + ' (average: ' 468 + str(sum(a.cycle_times) / len(a.cycle_times)) 469 + ')' 470 ) 471 tval = int(bs.apptime() * 1000.0) 472 assert isinstance(tval, int) 473 a.last_start_time = tval 474 475 assert a.text 476 a.text.text = '' 477 for spaz in list(a.spazzes.values()): 478 spaz.handlemessage(bs.DieMessage(immediate=True)) 479 a.spazzes = {} 480 a.current_spaz = None 481 for n in a.control_ui_nodes: 482 n.opacity = 0.0 483 a.set_stick_image_position(0, 0) 484 485 # Can be used for debugging. 486 class SetSpeed: 487 def __init__(self, speed: int): 488 self._speed = speed 489 490 def run(self, a: TutorialActivity) -> None: 491 print('setting to', self._speed) 492 bs.set_debug_speed_exponent(self._speed) 493 494 class RemoveGloves: 495 def __init__(self) -> None: 496 pass 497 498 def run(self, a: TutorialActivity) -> None: 499 # pylint: disable=protected-access 500 assert a.current_spaz is not None 501 # noinspection PyProtectedMember 502 a.current_spaz._gloves_wear_off() 503 504 class KillSpaz: 505 def __init__(self, num: int, explode: bool = False): 506 self._num = num 507 self._explode = explode 508 509 def run(self, a: TutorialActivity) -> None: 510 if self._explode: 511 a.spazzes[self._num].shatter() 512 del a.spazzes[self._num] 513 514 class SpawnSpaz: 515 def __init__( 516 self, 517 num: int, 518 position: Sequence[float], 519 color: Sequence[float] = (1.0, 1.0, 1.0), 520 make_current: bool = False, 521 relative_to: int | None = None, 522 name: str | bs.Lstr = '', 523 flash: bool = True, 524 angle: float = 0.0, 525 ): 526 self._num = num 527 self._position = position 528 self._make_current = make_current 529 self._color = color 530 self._relative_to = relative_to 531 self._name = name 532 self._flash = flash 533 self._angle = angle 534 535 def run(self, a: TutorialActivity) -> None: 536 # if they gave a 'relative to' spaz, position is relative 537 # to them 538 pos: Sequence[float] 539 if self._relative_to is not None: 540 snode = a.spazzes[self._relative_to].node 541 assert snode 542 their_pos = snode.position 543 pos = ( 544 their_pos[0] + self._position[0], 545 their_pos[1] + self._position[1], 546 their_pos[2] + self._position[2], 547 ) 548 else: 549 pos = self._position 550 551 # if there's already a spaz at this spot, insta-kill it 552 if self._num in a.spazzes: 553 a.spazzes[self._num].handlemessage( 554 bs.DieMessage(immediate=True) 555 ) 556 557 s = a.spazzes[self._num] = Spaz( 558 color=self._color, 559 start_invincible=self._flash, 560 demo_mode=True, 561 ) 562 563 # FIXME: Should extend spaz to support Lstr names. 564 assert s.node 565 if isinstance(self._name, bs.Lstr): 566 s.node.name = self._name.evaluate() 567 else: 568 s.node.name = self._name 569 s.node.name_color = self._color 570 s.handlemessage(bs.StandMessage(pos, self._angle)) 571 if self._make_current: 572 a.current_spaz = s 573 if self._flash: 574 a.spawn_sound.play(position=pos) 575 576 class Powerup: 577 def __init__( 578 self, 579 num: int, 580 position: Sequence[float], 581 color: Sequence[float] = (1.0, 1.0, 1.0), 582 make_current: bool = False, 583 relative_to: int | None = None, 584 ): 585 self._position = position 586 self._relative_to = relative_to 587 588 def run(self, a: TutorialActivity) -> None: 589 # If they gave a 'relative to' spaz, position is relative 590 # to them. 591 pos: Sequence[float] 592 if self._relative_to is not None: 593 snode = a.spazzes[self._relative_to].node 594 assert snode 595 their_pos = snode.position 596 pos = ( 597 their_pos[0] + self._position[0], 598 their_pos[1] + self._position[1], 599 their_pos[2] + self._position[2], 600 ) 601 else: 602 pos = self._position 603 from bascenev1lib.actor import powerupbox 604 605 powerupbox.PowerupBox( 606 position=pos, poweruptype='punch' 607 ).autoretain() 608 609 class Delay: 610 def __init__(self, time: int) -> None: 611 self._time = time 612 613 def run(self, a: TutorialActivity) -> int: 614 return self._time 615 616 class AnalyticsScreen: 617 def __init__(self, screen: str) -> None: 618 self._screen = screen 619 620 def run(self, a: TutorialActivity) -> None: 621 bs.set_analytics_screen(self._screen) 622 623 class DelayOld: 624 def __init__(self, time: int) -> None: 625 self._time = time 626 627 def run(self, a: TutorialActivity) -> int: 628 return int(0.9 * self._time) 629 630 class DelayOld2: 631 def __init__(self, time: int) -> None: 632 self._time = time 633 634 def run(self, a: TutorialActivity) -> int: 635 return int(0.8 * self._time) 636 637 class End: 638 def __init__(self) -> None: 639 pass 640 641 def run(self, a: TutorialActivity) -> None: 642 bs.increment_analytics_count('Tutorial finish') 643 a.end() 644 645 class Move: 646 def __init__(self, x: float, y: float): 647 self._x = float(x) 648 self._y = float(y) 649 650 def run(self, a: TutorialActivity) -> None: 651 s = a.current_spaz 652 assert s 653 # FIXME: Game should take floats for this. 654 x_clamped = self._x 655 y_clamped = self._y 656 s.on_move_left_right(x_clamped) 657 s.on_move_up_down(y_clamped) 658 a.set_stick_image_position(self._x, self._y) 659 660 class MoveLR: 661 def __init__(self, x: float): 662 self._x = float(x) 663 664 def run(self, a: TutorialActivity) -> None: 665 s = a.current_spaz 666 assert s 667 # FIXME: Game should take floats for this. 668 x_clamped = self._x 669 s.on_move_left_right(x_clamped) 670 a.set_stick_image_position( 671 self._x, a.stick_image_position_y 672 ) 673 674 class MoveUD: 675 def __init__(self, y: float): 676 self._y = float(y) 677 678 def run(self, a: TutorialActivity) -> None: 679 s = a.current_spaz 680 assert s 681 # FIXME: Game should take floats for this. 682 y_clamped = self._y 683 s.on_move_up_down(y_clamped) 684 a.set_stick_image_position( 685 a.stick_image_position_x, self._y 686 ) 687 688 class Bomb(ButtonPress): 689 def __init__( 690 self, 691 delay: int = 0, 692 release: bool = True, 693 release_delay: int = 500, 694 ): 695 ButtonPress.__init__( 696 self, 697 'bomb', 698 delay=delay, 699 release=release, 700 release_delay=release_delay, 701 ) 702 703 class Jump(ButtonPress): 704 def __init__( 705 self, 706 delay: int = 0, 707 release: bool = True, 708 release_delay: int = 500, 709 ): 710 ButtonPress.__init__( 711 self, 712 'jump', 713 delay=delay, 714 release=release, 715 release_delay=release_delay, 716 ) 717 718 class Punch(ButtonPress): 719 def __init__( 720 self, 721 delay: int = 0, 722 release: bool = True, 723 release_delay: int = 500, 724 ): 725 ButtonPress.__init__( 726 self, 727 'punch', 728 delay=delay, 729 release=release, 730 release_delay=release_delay, 731 ) 732 733 class PickUp(ButtonPress): 734 def __init__( 735 self, 736 delay: int = 0, 737 release: bool = True, 738 release_delay: int = 500, 739 ): 740 ButtonPress.__init__( 741 self, 742 'pickUp', 743 delay=delay, 744 release=release, 745 release_delay=release_delay, 746 ) 747 748 class Run(ButtonPress): 749 def __init__( 750 self, 751 delay: int = 0, 752 release: bool = True, 753 release_delay: int = 500, 754 ): 755 ButtonPress.__init__( 756 self, 757 'run', 758 delay=delay, 759 release=release, 760 release_delay=release_delay, 761 ) 762 763 class BombRelease(ButtonRelease): 764 def __init__(self, delay: int = 0): 765 super().__init__('bomb', delay=delay) 766 767 class JumpRelease(ButtonRelease): 768 def __init__(self, delay: int = 0): 769 super().__init__('jump', delay=delay) 770 771 class PunchRelease(ButtonRelease): 772 def __init__(self, delay: int = 0): 773 super().__init__('punch', delay=delay) 774 775 class PickUpRelease(ButtonRelease): 776 def __init__(self, delay: int = 0): 777 super().__init__('pickUp', delay=delay) 778 779 class RunRelease(ButtonRelease): 780 def __init__(self, delay: int = 0): 781 super().__init__('run', delay=delay) 782 783 class ShowControls: 784 def __init__(self) -> None: 785 pass 786 787 def run(self, a: TutorialActivity) -> None: 788 for n in a.control_ui_nodes: 789 bs.animate(n, 'opacity', {0.0: 0.0, 1.0: 1.0}) 790 791 class Text: 792 def __init__(self, text: str | bs.Lstr): 793 self.text = text 794 795 def run(self, a: TutorialActivity) -> None: 796 assert a.text 797 a.text.text = self.text 798 799 class PrintPos: 800 def __init__(self, spaz_num: int | None = None): 801 self._spaz_num = spaz_num 802 803 def run(self, a: TutorialActivity) -> None: 804 if self._spaz_num is None: 805 s = a.current_spaz 806 else: 807 s = a.spazzes[self._spaz_num] 808 assert s and s.node 809 t = list(s.node.position) 810 print('RestorePos(' + str((t[0], t[1] - 1.0, t[2])) + '),') 811 812 class RestorePos: 813 def __init__(self, pos: Sequence[float]) -> None: 814 self._pos = pos 815 816 def run(self, a: TutorialActivity) -> None: 817 s = a.current_spaz 818 assert s 819 s.handlemessage(bs.StandMessage(self._pos, 0)) 820 821 class Celebrate: 822 def __init__( 823 self, 824 celebrate_type: str = 'both', 825 spaz_num: int | None = None, 826 duration: int = 1000, 827 ): 828 self._spaz_num = spaz_num 829 self._celebrate_type = celebrate_type 830 self._duration = duration 831 832 def run(self, a: TutorialActivity) -> None: 833 if self._spaz_num is None: 834 s = a.current_spaz 835 else: 836 s = a.spazzes[self._spaz_num] 837 assert s and s.node 838 if self._celebrate_type == 'right': 839 s.node.handlemessage('celebrate_r', self._duration) 840 elif self._celebrate_type == 'left': 841 s.node.handlemessage('celebrate_l', self._duration) 842 elif self._celebrate_type == 'both': 843 s.node.handlemessage('celebrate', self._duration) 844 else: 845 raise RuntimeError( 846 'invalid celebrate type ' + self._celebrate_type 847 ) 848 849 self._entries = deque( 850 [ 851 Reset(), 852 SpawnSpaz(0, (0, 5.5, -3.0), make_current=True), 853 DelayOld(1000), 854 AnalyticsScreen('Tutorial Section 1'), 855 Text( 856 bs.Lstr(resource=f'{self._r}.phrase01Text') 857 ), # hi there 858 Celebrate('left'), 859 DelayOld(2000), 860 Text( 861 bs.Lstr( 862 resource=f'{self._r}.phrase02Text', 863 subs=[ 864 ('${APP_NAME}', bs.Lstr(resource='titleText')) 865 ], 866 ) 867 ), # welcome to <appname> 868 DelayOld(80), 869 Run(release=False), 870 Jump(release=False), 871 MoveLR(1), 872 MoveUD(0), 873 DelayOld(70), 874 RunRelease(), 875 JumpRelease(), 876 DelayOld(60), 877 MoveUD(1), 878 DelayOld(30), 879 MoveLR(0), 880 DelayOld(90), 881 MoveLR(-1), 882 DelayOld(20), 883 MoveUD(0), 884 DelayOld(70), 885 MoveUD(-1), 886 DelayOld(20), 887 MoveLR(0), 888 DelayOld(80), 889 MoveUD(0), 890 DelayOld(1500), 891 Text( 892 bs.Lstr(resource=f'{self._r}.phrase03Text') 893 ), # here's a few tips 894 DelayOld(1000), 895 ShowControls(), 896 DelayOld(1000), 897 Jump(), 898 DelayOld(1000), 899 Jump(), 900 DelayOld(1000), 901 AnalyticsScreen('Tutorial Section 2'), 902 Text( 903 bs.Lstr( 904 resource=f'{self._r}.phrase04Text', 905 subs=[ 906 ('${APP_NAME}', bs.Lstr(resource='titleText')) 907 ], 908 ) 909 ), # many things are based on physics 910 DelayOld(20), 911 MoveUD(0), 912 DelayOld(60), 913 MoveLR(0), 914 DelayOld(10), 915 MoveLR(0), 916 MoveUD(0), 917 DelayOld(10), 918 MoveLR(0), 919 MoveUD(0), 920 DelayOld(20), 921 MoveUD(-0.0575579), 922 DelayOld(10), 923 MoveUD(-0.207831), 924 DelayOld(30), 925 MoveUD(-0.309793), 926 DelayOld(10), 927 MoveUD(-0.474502), 928 DelayOld(10), 929 MoveLR(0.00390637), 930 MoveUD(-0.647053), 931 DelayOld(20), 932 MoveLR(-0.0745262), 933 MoveUD(-0.819605), 934 DelayOld(10), 935 MoveLR(-0.168645), 936 MoveUD(-0.937254), 937 DelayOld(30), 938 MoveLR(-0.294137), 939 MoveUD(-1), 940 DelayOld(10), 941 MoveLR(-0.411786), 942 DelayOld(10), 943 MoveLR(-0.639241), 944 DelayOld(30), 945 MoveLR(-0.75689), 946 DelayOld(10), 947 MoveLR(-0.905911), 948 DelayOld(20), 949 MoveLR(-1), 950 DelayOld(50), 951 MoveUD(-0.960784), 952 DelayOld(20), 953 MoveUD(-0.819605), 954 MoveUD(-0.61568), 955 DelayOld(20), 956 MoveUD(-0.427442), 957 DelayOld(20), 958 MoveUD(-0.231361), 959 DelayOld(10), 960 MoveUD(-0.00390637), 961 DelayOld(30), 962 MoveUD(0.333354), 963 MoveUD(0.584338), 964 DelayOld(20), 965 MoveUD(0.764733), 966 DelayOld(30), 967 MoveLR(-0.803949), 968 MoveUD(0.913755), 969 DelayOld(10), 970 MoveLR(-0.647084), 971 MoveUD(0.992187), 972 DelayOld(20), 973 MoveLR(-0.435316), 974 MoveUD(1), 975 DelayOld(20), 976 MoveLR(-0.168645), 977 MoveUD(0.976501), 978 MoveLR(0.0744957), 979 MoveUD(0.905911), 980 DelayOld(20), 981 MoveLR(0.270577), 982 MoveUD(0.843165), 983 DelayOld(20), 984 MoveLR(0.435286), 985 MoveUD(0.780419), 986 DelayOld(10), 987 MoveLR(0.66274), 988 MoveUD(0.647084), 989 DelayOld(30), 990 MoveLR(0.803919), 991 MoveUD(0.458846), 992 MoveLR(0.929411), 993 MoveUD(0.223548), 994 DelayOld(20), 995 MoveLR(0.95294), 996 MoveUD(0.137272), 997 DelayOld(20), 998 MoveLR(1), 999 MoveUD(-0.0509659), 1000 DelayOld(20), 1001 MoveUD(-0.247047), 1002 DelayOld(20), 1003 MoveUD(-0.443129), 1004 DelayOld(20), 1005 MoveUD(-0.694113), 1006 MoveUD(-0.921567), 1007 DelayOld(30), 1008 MoveLR(0.858821), 1009 MoveUD(-1), 1010 DelayOld(10), 1011 MoveLR(0.68627), 1012 DelayOld(10), 1013 MoveLR(0.364696), 1014 DelayOld(20), 1015 MoveLR(0.0509659), 1016 DelayOld(20), 1017 MoveLR(-0.223548), 1018 DelayOld(10), 1019 MoveLR(-0.600024), 1020 MoveUD(-0.913724), 1021 DelayOld(30), 1022 MoveLR(-0.858852), 1023 MoveUD(-0.717643), 1024 MoveLR(-1), 1025 MoveUD(-0.474502), 1026 DelayOld(20), 1027 MoveUD(-0.396069), 1028 DelayOld(20), 1029 MoveUD(-0.286264), 1030 DelayOld(20), 1031 MoveUD(-0.137242), 1032 DelayOld(20), 1033 MoveUD(0.0353099), 1034 DelayOld(10), 1035 MoveUD(0.32551), 1036 DelayOld(20), 1037 MoveUD(0.592181), 1038 DelayOld(10), 1039 MoveUD(0.851009), 1040 DelayOld(10), 1041 MoveUD(1), 1042 DelayOld(30), 1043 MoveLR(-0.764733), 1044 DelayOld(20), 1045 MoveLR(-0.403943), 1046 MoveLR(-0.145116), 1047 DelayOld(30), 1048 MoveLR(0.0901822), 1049 MoveLR(0.32548), 1050 DelayOld(30), 1051 MoveLR(0.560778), 1052 MoveUD(0.929441), 1053 DelayOld(20), 1054 MoveLR(0.709799), 1055 MoveUD(0.73336), 1056 MoveLR(0.803919), 1057 MoveUD(0.545122), 1058 DelayOld(20), 1059 MoveLR(0.882351), 1060 MoveUD(0.356883), 1061 DelayOld(10), 1062 MoveLR(0.968627), 1063 MoveUD(0.113742), 1064 DelayOld(20), 1065 MoveLR(0.992157), 1066 MoveUD(-0.0823389), 1067 DelayOld(30), 1068 MoveUD(-0.309793), 1069 DelayOld(10), 1070 MoveUD(-0.545091), 1071 DelayOld(20), 1072 MoveLR(0.882351), 1073 MoveUD(-0.874508), 1074 DelayOld(20), 1075 MoveLR(0.756859), 1076 MoveUD(-1), 1077 DelayOld(10), 1078 MoveLR(0.576464), 1079 DelayOld(20), 1080 MoveLR(0.254891), 1081 DelayOld(10), 1082 MoveLR(-0.0274667), 1083 DelayOld(10), 1084 MoveLR(-0.356883), 1085 DelayOld(30), 1086 MoveLR(-0.592181), 1087 MoveLR(-0.827479), 1088 MoveUD(-0.921567), 1089 DelayOld(20), 1090 MoveLR(-1), 1091 MoveUD(-0.749016), 1092 DelayOld(20), 1093 MoveUD(-0.61568), 1094 DelayOld(10), 1095 MoveUD(-0.403912), 1096 DelayOld(20), 1097 MoveUD(-0.207831), 1098 DelayOld(10), 1099 MoveUD(0.121586), 1100 DelayOld(30), 1101 MoveUD(0.34904), 1102 DelayOld(10), 1103 MoveUD(0.560808), 1104 DelayOld(10), 1105 MoveUD(0.827479), 1106 DelayOld(30), 1107 MoveUD(1), 1108 DelayOld(20), 1109 MoveLR(-0.976501), 1110 MoveLR(-0.670614), 1111 DelayOld(20), 1112 MoveLR(-0.239235), 1113 DelayOld(20), 1114 MoveLR(0.160772), 1115 DelayOld(20), 1116 MoveLR(0.443129), 1117 DelayOld(10), 1118 MoveLR(0.68627), 1119 MoveUD(0.976501), 1120 DelayOld(30), 1121 MoveLR(0.929411), 1122 MoveUD(0.73336), 1123 MoveLR(1), 1124 MoveUD(0.482376), 1125 DelayOld(20), 1126 MoveUD(0.34904), 1127 DelayOld(10), 1128 MoveUD(0.160802), 1129 DelayOld(30), 1130 MoveUD(-0.0744957), 1131 DelayOld(10), 1132 MoveUD(-0.333323), 1133 DelayOld(20), 1134 MoveUD(-0.647053), 1135 DelayOld(20), 1136 MoveUD(-0.937254), 1137 DelayOld(10), 1138 MoveLR(0.858821), 1139 MoveUD(-1), 1140 DelayOld(10), 1141 MoveLR(0.576464), 1142 DelayOld(30), 1143 MoveLR(0.184301), 1144 DelayOld(10), 1145 MoveLR(-0.121586), 1146 DelayOld(10), 1147 MoveLR(-0.474532), 1148 DelayOld(30), 1149 MoveLR(-0.670614), 1150 MoveLR(-0.851009), 1151 DelayOld(30), 1152 MoveLR(-1), 1153 MoveUD(-0.968627), 1154 DelayOld(20), 1155 MoveUD(-0.843135), 1156 DelayOld(10), 1157 MoveUD(-0.631367), 1158 DelayOld(20), 1159 MoveUD(-0.403912), 1160 MoveUD(-0.176458), 1161 DelayOld(20), 1162 MoveUD(0.0902127), 1163 DelayOld(20), 1164 MoveUD(0.380413), 1165 DelayOld(10), 1166 MoveUD(0.717673), 1167 DelayOld(30), 1168 MoveUD(1), 1169 DelayOld(10), 1170 MoveLR(-0.741203), 1171 DelayOld(20), 1172 MoveLR(-0.458846), 1173 DelayOld(10), 1174 MoveLR(-0.145116), 1175 DelayOld(10), 1176 MoveLR(0.0980255), 1177 DelayOld(20), 1178 MoveLR(0.294107), 1179 DelayOld(30), 1180 MoveLR(0.466659), 1181 MoveLR(0.717643), 1182 MoveUD(0.796106), 1183 DelayOld(20), 1184 MoveLR(0.921567), 1185 MoveUD(0.443159), 1186 DelayOld(20), 1187 MoveLR(1), 1188 MoveUD(0.145116), 1189 DelayOld(10), 1190 MoveUD(-0.0274361), 1191 DelayOld(30), 1192 MoveUD(-0.223518), 1193 MoveUD(-0.427442), 1194 DelayOld(20), 1195 MoveUD(-0.874508), 1196 DelayOld(20), 1197 MoveUD(-1), 1198 DelayOld(10), 1199 MoveLR(0.929411), 1200 DelayOld(20), 1201 MoveLR(0.68627), 1202 DelayOld(20), 1203 MoveLR(0.364696), 1204 DelayOld(20), 1205 MoveLR(0.0431227), 1206 DelayOld(10), 1207 MoveLR(-0.333354), 1208 DelayOld(20), 1209 MoveLR(-0.639241), 1210 DelayOld(20), 1211 MoveLR(-0.968657), 1212 MoveUD(-0.968627), 1213 DelayOld(20), 1214 MoveLR(-1), 1215 MoveUD(-0.890194), 1216 MoveUD(-0.866665), 1217 DelayOld(20), 1218 MoveUD(-0.749016), 1219 DelayOld(20), 1220 MoveUD(-0.529405), 1221 DelayOld(20), 1222 MoveUD(-0.30195), 1223 DelayOld(10), 1224 MoveUD(-0.00390637), 1225 DelayOld(10), 1226 MoveUD(0.262764), 1227 DelayOld(30), 1228 MoveLR(-0.600024), 1229 MoveUD(0.458846), 1230 DelayOld(10), 1231 MoveLR(-0.294137), 1232 MoveUD(0.482376), 1233 DelayOld(20), 1234 MoveLR(-0.200018), 1235 MoveUD(0.505905), 1236 DelayOld(10), 1237 MoveLR(-0.145116), 1238 MoveUD(0.545122), 1239 DelayOld(20), 1240 MoveLR(-0.0353099), 1241 MoveUD(0.584338), 1242 DelayOld(20), 1243 MoveLR(0.137242), 1244 MoveUD(0.592181), 1245 DelayOld(20), 1246 MoveLR(0.30195), 1247 DelayOld(10), 1248 MoveLR(0.490188), 1249 DelayOld(10), 1250 MoveLR(0.599994), 1251 MoveUD(0.529435), 1252 DelayOld(30), 1253 MoveLR(0.66274), 1254 MoveUD(0.3961), 1255 DelayOld(20), 1256 MoveLR(0.670583), 1257 MoveUD(0.231391), 1258 MoveLR(0.68627), 1259 MoveUD(0.0745262), 1260 Move(0, -0.01), 1261 DelayOld(100), 1262 Move(0, 0), 1263 DelayOld(1000), 1264 Text( 1265 bs.Lstr(resource=f'{self._r}.phrase05Text') 1266 ), # for example when you punch.. 1267 DelayOld(510), 1268 Move(0, -0.01), 1269 DelayOld(100), 1270 Move(0, 0), 1271 DelayOld(500), 1272 SpawnSpaz( 1273 0, 1274 (-0.09249162673950195, 4.337906360626221, -2.3), 1275 make_current=True, 1276 flash=False, 1277 ), 1278 SpawnSpaz( 1279 1, 1280 (-3.1, 4.3, -2.0), 1281 make_current=False, 1282 color=(1, 1, 0.4), 1283 name=bs.Lstr(resource=f'{self._r}.randomName1Text'), 1284 ), 1285 Move(-1.0, 0), 1286 DelayOld(1050), 1287 Move(0, -0.01), 1288 DelayOld(100), 1289 Move(0, 0), 1290 DelayOld(1000), 1291 Text( 1292 bs.Lstr(resource=f'{self._r}.phrase06Text') 1293 ), # your damage is based 1294 DelayOld(1200), 1295 Move(-0.05, 0), 1296 DelayOld(200), 1297 Punch(), 1298 DelayOld(800), 1299 Punch(), 1300 DelayOld(800), 1301 Punch(), 1302 DelayOld(800), 1303 Move(0, -0.01), 1304 DelayOld(100), 1305 Move(0, 0), 1306 Text( 1307 bs.Lstr( 1308 resource=f'{self._r}.phrase07Text', 1309 subs=[ 1310 ( 1311 '${NAME}', 1312 bs.Lstr( 1313 resource=f'{self._r}.randomName1Text' 1314 ), 1315 ) 1316 ], 1317 ) 1318 ), # see that didn't hurt fred 1319 DelayOld(2000), 1320 Celebrate('right', spaz_num=1), 1321 DelayOld(1400), 1322 Text( 1323 bs.Lstr(resource=f'{self._r}.phrase08Text') 1324 ), # lets jump and spin to get more speed 1325 DelayOld(30), 1326 MoveLR(0), 1327 DelayOld(40), 1328 MoveLR(0), 1329 DelayOld(40), 1330 MoveLR(0), 1331 DelayOld(130), 1332 MoveLR(0), 1333 DelayOld(100), 1334 MoveLR(0), 1335 DelayOld(10), 1336 MoveLR(0.0480667), 1337 DelayOld(40), 1338 MoveLR(0.056093), 1339 MoveLR(0.0681173), 1340 DelayOld(30), 1341 MoveLR(0.0801416), 1342 DelayOld(10), 1343 MoveLR(0.184301), 1344 DelayOld(10), 1345 MoveLR(0.207831), 1346 DelayOld(20), 1347 MoveLR(0.231361), 1348 DelayOld(30), 1349 MoveLR(0.239204), 1350 DelayOld(30), 1351 MoveLR(0.254891), 1352 DelayOld(40), 1353 MoveLR(0.270577), 1354 DelayOld(10), 1355 MoveLR(0.30195), 1356 DelayOld(20), 1357 MoveLR(0.341166), 1358 DelayOld(30), 1359 MoveLR(0.388226), 1360 MoveLR(0.435286), 1361 DelayOld(30), 1362 MoveLR(0.490188), 1363 DelayOld(10), 1364 MoveLR(0.560778), 1365 DelayOld(20), 1366 MoveLR(0.599994), 1367 DelayOld(10), 1368 MoveLR(0.647053), 1369 DelayOld(10), 1370 MoveLR(0.68627), 1371 DelayOld(30), 1372 MoveLR(0.733329), 1373 DelayOld(20), 1374 MoveLR(0.764702), 1375 DelayOld(10), 1376 MoveLR(0.827448), 1377 DelayOld(20), 1378 MoveLR(0.874508), 1379 DelayOld(20), 1380 MoveLR(0.929411), 1381 DelayOld(10), 1382 MoveLR(1), 1383 DelayOld(830), 1384 MoveUD(0.0274667), 1385 DelayOld(10), 1386 MoveLR(0.95294), 1387 MoveUD(0.113742), 1388 DelayOld(30), 1389 MoveLR(0.780389), 1390 MoveUD(0.184332), 1391 DelayOld(10), 1392 MoveLR(0.27842), 1393 MoveUD(0.0745262), 1394 DelayOld(20), 1395 MoveLR(0), 1396 MoveUD(0), 1397 DelayOld(390), 1398 MoveLR(0), 1399 MoveLR(0), 1400 DelayOld(20), 1401 MoveLR(0), 1402 DelayOld(20), 1403 MoveLR(0), 1404 DelayOld(10), 1405 MoveLR(-0.0537431), 1406 DelayOld(20), 1407 MoveLR(-0.215705), 1408 DelayOld(30), 1409 MoveLR(-0.388256), 1410 MoveLR(-0.529435), 1411 DelayOld(30), 1412 MoveLR(-0.694143), 1413 DelayOld(20), 1414 MoveLR(-0.851009), 1415 MoveUD(0.0588397), 1416 DelayOld(10), 1417 MoveLR(-1), 1418 MoveUD(0.0745262), 1419 Run(release=False), 1420 DelayOld(200), 1421 MoveUD(0.0509964), 1422 DelayOld(30), 1423 MoveUD(0.0117801), 1424 DelayOld(20), 1425 MoveUD(-0.0901822), 1426 MoveUD(-0.372539), 1427 DelayOld(30), 1428 MoveLR(-0.898068), 1429 MoveUD(-0.890194), 1430 Jump(release=False), 1431 DelayOld(20), 1432 MoveLR(-0.647084), 1433 MoveUD(-1), 1434 MoveLR(-0.427473), 1435 DelayOld(20), 1436 MoveLR(-0.00393689), 1437 DelayOld(10), 1438 MoveLR(0.537248), 1439 DelayOld(30), 1440 MoveLR(1), 1441 DelayOld(50), 1442 RunRelease(), 1443 JumpRelease(), 1444 DelayOld(50), 1445 MoveUD(-0.921567), 1446 MoveUD(-0.749016), 1447 DelayOld(30), 1448 MoveUD(-0.552934), 1449 DelayOld(10), 1450 MoveUD(-0.247047), 1451 DelayOld(20), 1452 MoveUD(0.200018), 1453 DelayOld(20), 1454 MoveUD(0.670614), 1455 MoveUD(1), 1456 DelayOld(70), 1457 MoveLR(0.97647), 1458 DelayOld(20), 1459 MoveLR(0.764702), 1460 DelayOld(20), 1461 MoveLR(0.364696), 1462 DelayOld(20), 1463 MoveLR(0.00390637), 1464 MoveLR(-0.309824), 1465 DelayOld(20), 1466 MoveLR(-0.576495), 1467 DelayOld(30), 1468 MoveLR(-0.898068), 1469 DelayOld(10), 1470 MoveLR(-1), 1471 MoveUD(0.905911), 1472 DelayOld(20), 1473 MoveUD(0.498062), 1474 DelayOld(20), 1475 MoveUD(0.0274667), 1476 MoveUD(-0.403912), 1477 DelayOld(20), 1478 MoveUD(-1), 1479 Run(release=False), 1480 Jump(release=False), 1481 DelayOld(10), 1482 Punch(release=False), 1483 DelayOld(70), 1484 JumpRelease(), 1485 DelayOld(110), 1486 MoveLR(-0.976501), 1487 RunRelease(), 1488 PunchRelease(), 1489 DelayOld(10), 1490 MoveLR(-0.952971), 1491 DelayOld(20), 1492 MoveLR(-0.905911), 1493 MoveLR(-0.827479), 1494 DelayOld(20), 1495 MoveLR(-0.75689), 1496 DelayOld(30), 1497 MoveLR(-0.73336), 1498 MoveLR(-0.694143), 1499 DelayOld(20), 1500 MoveLR(-0.670614), 1501 DelayOld(30), 1502 MoveLR(-0.66277), 1503 DelayOld(10), 1504 MoveUD(-0.960784), 1505 DelayOld(20), 1506 MoveLR(-0.623554), 1507 MoveUD(-0.874508), 1508 DelayOld(10), 1509 MoveLR(-0.545122), 1510 MoveUD(-0.694113), 1511 DelayOld(20), 1512 MoveLR(-0.505905), 1513 MoveUD(-0.474502), 1514 DelayOld(20), 1515 MoveLR(-0.458846), 1516 MoveUD(-0.356853), 1517 MoveLR(-0.364727), 1518 MoveUD(-0.27842), 1519 DelayOld(20), 1520 MoveLR(0.00390637), 1521 Move(0, 0), 1522 DelayOld(1000), 1523 Text( 1524 bs.Lstr(resource=f'{self._r}.phrase09Text') 1525 ), # ah that's better 1526 DelayOld(1900), 1527 AnalyticsScreen('Tutorial Section 3'), 1528 Text( 1529 bs.Lstr(resource=f'{self._r}.phrase10Text') 1530 ), # running also helps 1531 DelayOld(100), 1532 SpawnSpaz( 1533 0, (-3.2, 4.3, -4.4), make_current=True, flash=False 1534 ), 1535 SpawnSpaz( 1536 1, 1537 (3.3, 4.2, -5.8), 1538 make_current=False, 1539 color=(0.9, 0.5, 1.0), 1540 name=bs.Lstr(resource=f'{self._r}.randomName2Text'), 1541 ), 1542 DelayOld(1800), 1543 Text( 1544 bs.Lstr(resource=f'{self._r}.phrase11Text') 1545 ), # hold ANY button to run 1546 DelayOld(300), 1547 MoveUD(0), 1548 DelayOld(20), 1549 MoveUD(-0.0520646), 1550 DelayOld(20), 1551 MoveLR(0), 1552 MoveUD(-0.223518), 1553 Run(release=False), 1554 Jump(release=False), 1555 DelayOld(10), 1556 MoveLR(0.0980255), 1557 MoveUD(-0.309793), 1558 DelayOld(30), 1559 MoveLR(0.160772), 1560 MoveUD(-0.427442), 1561 DelayOld(20), 1562 MoveLR(0.231361), 1563 MoveUD(-0.545091), 1564 DelayOld(10), 1565 MoveLR(0.317637), 1566 MoveUD(-0.678426), 1567 DelayOld(20), 1568 MoveLR(0.396069), 1569 MoveUD(-0.819605), 1570 MoveLR(0.482345), 1571 MoveUD(-0.913724), 1572 DelayOld(20), 1573 MoveLR(0.560778), 1574 MoveUD(-1), 1575 DelayOld(20), 1576 MoveLR(0.607837), 1577 DelayOld(10), 1578 MoveLR(0.623524), 1579 DelayOld(30), 1580 MoveLR(0.647053), 1581 DelayOld(20), 1582 MoveLR(0.670583), 1583 MoveLR(0.694113), 1584 DelayOld(30), 1585 MoveLR(0.733329), 1586 DelayOld(20), 1587 MoveLR(0.764702), 1588 MoveLR(0.788232), 1589 DelayOld(20), 1590 MoveLR(0.827448), 1591 DelayOld(10), 1592 MoveLR(0.858821), 1593 DelayOld(20), 1594 MoveLR(0.921567), 1595 DelayOld(30), 1596 MoveLR(0.97647), 1597 MoveLR(1), 1598 DelayOld(130), 1599 MoveUD(-0.960784), 1600 DelayOld(20), 1601 MoveUD(-0.921567), 1602 DelayOld(30), 1603 MoveUD(-0.866665), 1604 MoveUD(-0.819605), 1605 DelayOld(30), 1606 MoveUD(-0.772546), 1607 MoveUD(-0.725486), 1608 DelayOld(30), 1609 MoveUD(-0.631367), 1610 DelayOld(10), 1611 MoveUD(-0.552934), 1612 DelayOld(20), 1613 MoveUD(-0.474502), 1614 DelayOld(10), 1615 MoveUD(-0.403912), 1616 DelayOld(30), 1617 MoveUD(-0.356853), 1618 DelayOld(30), 1619 MoveUD(-0.34901), 1620 DelayOld(20), 1621 MoveUD(-0.333323), 1622 DelayOld(20), 1623 MoveUD(-0.32548), 1624 DelayOld(10), 1625 MoveUD(-0.30195), 1626 DelayOld(20), 1627 MoveUD(-0.27842), 1628 DelayOld(30), 1629 MoveUD(-0.254891), 1630 MoveUD(-0.231361), 1631 DelayOld(30), 1632 MoveUD(-0.207831), 1633 DelayOld(20), 1634 MoveUD(-0.199988), 1635 MoveUD(-0.176458), 1636 DelayOld(30), 1637 MoveUD(-0.137242), 1638 MoveUD(-0.0823389), 1639 DelayOld(20), 1640 MoveUD(-0.0274361), 1641 DelayOld(20), 1642 MoveUD(0.00393689), 1643 DelayOld(40), 1644 MoveUD(0.0353099), 1645 DelayOld(20), 1646 MoveUD(0.113742), 1647 DelayOld(10), 1648 MoveUD(0.137272), 1649 DelayOld(20), 1650 MoveUD(0.160802), 1651 MoveUD(0.184332), 1652 DelayOld(20), 1653 MoveUD(0.207862), 1654 DelayOld(30), 1655 MoveUD(0.247078), 1656 MoveUD(0.262764), 1657 DelayOld(20), 1658 MoveUD(0.270608), 1659 DelayOld(30), 1660 MoveUD(0.294137), 1661 MoveUD(0.32551), 1662 DelayOld(30), 1663 MoveUD(0.37257), 1664 Celebrate('left', 1), 1665 DelayOld(20), 1666 MoveUD(0.498062), 1667 MoveUD(0.560808), 1668 DelayOld(30), 1669 MoveUD(0.654927), 1670 MoveUD(0.694143), 1671 DelayOld(30), 1672 MoveUD(0.741203), 1673 DelayOld(20), 1674 MoveUD(0.780419), 1675 MoveUD(0.819636), 1676 DelayOld(20), 1677 MoveUD(0.843165), 1678 DelayOld(20), 1679 MoveUD(0.882382), 1680 DelayOld(10), 1681 MoveUD(0.913755), 1682 DelayOld(30), 1683 MoveUD(0.968657), 1684 MoveUD(1), 1685 DelayOld(560), 1686 Punch(release=False), 1687 DelayOld(210), 1688 MoveUD(0.968657), 1689 DelayOld(30), 1690 MoveUD(0.75689), 1691 PunchRelease(), 1692 DelayOld(20), 1693 MoveLR(0.95294), 1694 MoveUD(0.435316), 1695 RunRelease(), 1696 JumpRelease(), 1697 MoveLR(0.811762), 1698 MoveUD(0.270608), 1699 DelayOld(20), 1700 MoveLR(0.670583), 1701 MoveUD(0.160802), 1702 DelayOld(20), 1703 MoveLR(0.466659), 1704 MoveUD(0.0588397), 1705 DelayOld(10), 1706 MoveLR(0.317637), 1707 MoveUD(-0.00390637), 1708 DelayOld(20), 1709 MoveLR(0.0801416), 1710 DelayOld(10), 1711 MoveLR(0), 1712 DelayOld(20), 1713 MoveLR(0), 1714 DelayOld(30), 1715 MoveLR(0), 1716 DelayOld(30), 1717 MoveLR(0), 1718 DelayOld(20), 1719 MoveLR(0), 1720 DelayOld(100), 1721 MoveLR(0), 1722 DelayOld(30), 1723 MoveUD(0), 1724 DelayOld(30), 1725 MoveUD(0), 1726 DelayOld(50), 1727 MoveUD(0), 1728 MoveUD(0), 1729 DelayOld(30), 1730 MoveLR(0), 1731 MoveUD(-0.0520646), 1732 MoveLR(0), 1733 MoveUD(-0.0640889), 1734 DelayOld(20), 1735 MoveLR(0), 1736 MoveUD(-0.0881375), 1737 DelayOld(30), 1738 MoveLR(-0.0498978), 1739 MoveUD(-0.199988), 1740 MoveLR(-0.121586), 1741 MoveUD(-0.207831), 1742 DelayOld(20), 1743 MoveLR(-0.145116), 1744 MoveUD(-0.223518), 1745 DelayOld(30), 1746 MoveLR(-0.152959), 1747 MoveUD(-0.231361), 1748 MoveLR(-0.192175), 1749 MoveUD(-0.262734), 1750 DelayOld(30), 1751 MoveLR(-0.200018), 1752 MoveUD(-0.27842), 1753 DelayOld(20), 1754 MoveLR(-0.239235), 1755 MoveUD(-0.30195), 1756 MoveUD(-0.309793), 1757 DelayOld(40), 1758 MoveUD(-0.333323), 1759 DelayOld(10), 1760 MoveUD(-0.34901), 1761 DelayOld(30), 1762 MoveUD(-0.372539), 1763 MoveUD(-0.396069), 1764 DelayOld(20), 1765 MoveUD(-0.443129), 1766 DelayOld(20), 1767 MoveUD(-0.458815), 1768 DelayOld(10), 1769 MoveUD(-0.474502), 1770 DelayOld(50), 1771 MoveUD(-0.482345), 1772 DelayOld(30), 1773 MoveLR(-0.215705), 1774 DelayOld(30), 1775 MoveLR(-0.200018), 1776 DelayOld(10), 1777 MoveLR(-0.192175), 1778 DelayOld(10), 1779 MoveLR(-0.176489), 1780 DelayOld(30), 1781 MoveLR(-0.152959), 1782 DelayOld(20), 1783 MoveLR(-0.145116), 1784 MoveLR(-0.121586), 1785 MoveUD(-0.458815), 1786 DelayOld(30), 1787 MoveLR(-0.098056), 1788 MoveUD(-0.419599), 1789 DelayOld(10), 1790 MoveLR(-0.0745262), 1791 MoveUD(-0.333323), 1792 DelayOld(10), 1793 MoveLR(0.00390637), 1794 MoveUD(0), 1795 DelayOld(990), 1796 MoveLR(0), 1797 DelayOld(660), 1798 MoveUD(0), 1799 AnalyticsScreen('Tutorial Section 4'), 1800 Text( 1801 bs.Lstr(resource=f'{self._r}.phrase12Text') 1802 ), # for extra-awesome punches,... 1803 DelayOld(200), 1804 SpawnSpaz( 1805 0, 1806 ( 1807 2.368781805038452, 1808 4.337533950805664, 1809 -4.360159873962402, 1810 ), 1811 make_current=True, 1812 flash=False, 1813 ), 1814 SpawnSpaz( 1815 1, 1816 (-3.2, 4.3, -4.5), 1817 make_current=False, 1818 color=(1.0, 0.7, 0.3), 1819 # name=R.randomName3Text), 1820 name=bs.Lstr(resource=f'{self._r}.randomName3Text'), 1821 ), 1822 DelayOld(100), 1823 Powerup(1, (2.5, 0.0, 0), relative_to=0), 1824 Move(1, 0), 1825 DelayOld(1700), 1826 Move(0, -0.1), 1827 DelayOld(100), 1828 Move(0, 0), 1829 DelayOld(500), 1830 DelayOld(320), 1831 MoveLR(0), 1832 DelayOld(20), 1833 MoveLR(0), 1834 DelayOld(10), 1835 MoveLR(0), 1836 DelayOld(20), 1837 MoveLR(-0.333354), 1838 MoveLR(-0.592181), 1839 DelayOld(20), 1840 MoveLR(-0.788263), 1841 DelayOld(20), 1842 MoveLR(-1), 1843 MoveUD(0.0353099), 1844 MoveUD(0.0588397), 1845 DelayOld(10), 1846 Run(release=False), 1847 DelayOld(780), 1848 MoveUD(0.0274667), 1849 MoveUD(0.00393689), 1850 DelayOld(10), 1851 MoveUD(-0.00390637), 1852 DelayOld(440), 1853 MoveUD(0.0353099), 1854 DelayOld(20), 1855 MoveUD(0.0588397), 1856 DelayOld(10), 1857 MoveUD(0.0902127), 1858 DelayOld(260), 1859 MoveUD(0.0353099), 1860 DelayOld(30), 1861 MoveUD(0.00393689), 1862 DelayOld(10), 1863 MoveUD(-0.00390637), 1864 MoveUD(-0.0274361), 1865 Celebrate('left', 1), 1866 DelayOld(10), 1867 MoveUD(-0.0823389), 1868 DelayOld(30), 1869 MoveUD(-0.176458), 1870 MoveUD(-0.286264), 1871 DelayOld(20), 1872 MoveUD(-0.498032), 1873 Jump(release=False), 1874 MoveUD(-0.764702), 1875 DelayOld(30), 1876 MoveLR(-0.858852), 1877 MoveUD(-1), 1878 MoveLR(-0.780419), 1879 DelayOld(20), 1880 MoveLR(-0.717673), 1881 DelayOld(10), 1882 MoveLR(-0.552965), 1883 DelayOld(10), 1884 MoveLR(-0.341197), 1885 DelayOld(10), 1886 MoveLR(-0.0274667), 1887 DelayOld(10), 1888 MoveLR(0.27842), 1889 DelayOld(20), 1890 MoveLR(0.811762), 1891 MoveLR(1), 1892 RunRelease(), 1893 JumpRelease(), 1894 DelayOld(260), 1895 MoveLR(0.95294), 1896 DelayOld(30), 1897 MoveLR(0.756859), 1898 DelayOld(10), 1899 MoveLR(0.317637), 1900 MoveLR(-0.00393689), 1901 DelayOld(10), 1902 MoveLR(-0.341197), 1903 DelayOld(10), 1904 MoveLR(-0.647084), 1905 MoveUD(-0.921567), 1906 DelayOld(10), 1907 MoveLR(-1), 1908 MoveUD(-0.599994), 1909 MoveUD(-0.474502), 1910 DelayOld(10), 1911 MoveUD(-0.309793), 1912 DelayOld(10), 1913 MoveUD(-0.160772), 1914 MoveUD(-0.0352794), 1915 Delay(10), 1916 MoveUD(0.176489), 1917 Delay(10), 1918 MoveUD(0.607868), 1919 Run(release=False), 1920 Jump(release=False), 1921 DelayOld(20), 1922 MoveUD(1), 1923 DelayOld(30), 1924 MoveLR(-0.921598), 1925 DelayOld(10), 1926 Punch(release=False), 1927 MoveLR(-0.639241), 1928 DelayOld(10), 1929 MoveLR(-0.223548), 1930 DelayOld(10), 1931 MoveLR(0.254891), 1932 DelayOld(10), 1933 MoveLR(0.741172), 1934 MoveLR(1), 1935 DelayOld(40), 1936 JumpRelease(), 1937 DelayOld(40), 1938 MoveUD(0.976501), 1939 DelayOld(10), 1940 MoveUD(0.73336), 1941 DelayOld(10), 1942 MoveUD(0.309824), 1943 DelayOld(20), 1944 MoveUD(-0.184301), 1945 DelayOld(20), 1946 MoveUD(-0.811762), 1947 MoveUD(-1), 1948 KillSpaz(1, explode=True), 1949 DelayOld(10), 1950 RunRelease(), 1951 PunchRelease(), 1952 DelayOld(110), 1953 MoveLR(0.97647), 1954 MoveLR(0.898038), 1955 DelayOld(20), 1956 MoveLR(0.788232), 1957 DelayOld(20), 1958 MoveLR(0.670583), 1959 DelayOld(10), 1960 MoveLR(0.505875), 1961 DelayOld(10), 1962 MoveLR(0.32548), 1963 DelayOld(20), 1964 MoveLR(0.137242), 1965 DelayOld(10), 1966 MoveLR(-0.00393689), 1967 DelayOld(10), 1968 MoveLR(-0.215705), 1969 MoveLR(-0.356883), 1970 DelayOld(20), 1971 MoveLR(-0.451003), 1972 DelayOld(10), 1973 MoveLR(-0.552965), 1974 DelayOld(20), 1975 MoveLR(-0.670614), 1976 MoveLR(-0.780419), 1977 DelayOld(10), 1978 MoveLR(-0.898068), 1979 DelayOld(20), 1980 MoveLR(-1), 1981 DelayOld(370), 1982 MoveLR(-0.976501), 1983 DelayOld(10), 1984 MoveLR(-0.952971), 1985 DelayOld(10), 1986 MoveLR(-0.929441), 1987 MoveLR(-0.898068), 1988 DelayOld(30), 1989 MoveLR(-0.874538), 1990 DelayOld(10), 1991 MoveLR(-0.851009), 1992 DelayOld(10), 1993 MoveLR(-0.835322), 1994 MoveUD(-0.968627), 1995 DelayOld(10), 1996 MoveLR(-0.827479), 1997 MoveUD(-0.960784), 1998 DelayOld(20), 1999 MoveUD(-0.945097), 2000 DelayOld(70), 2001 MoveUD(-0.937254), 2002 DelayOld(20), 2003 MoveUD(-0.913724), 2004 DelayOld(20), 2005 MoveUD(-0.890194), 2006 MoveLR(-0.780419), 2007 MoveUD(-0.827448), 2008 DelayOld(20), 2009 MoveLR(0.317637), 2010 MoveUD(0.3961), 2011 MoveLR(0.0195929), 2012 MoveUD(0.056093), 2013 DelayOld(20), 2014 MoveUD(0), 2015 DelayOld(750), 2016 MoveLR(0), 2017 Text( 2018 bs.Lstr( 2019 resource=f'{self._r}.phrase13Text', 2020 subs=[ 2021 ( 2022 '${NAME}', 2023 bs.Lstr( 2024 resource=f'{self._r}.randomName3Text' 2025 ), 2026 ) 2027 ], 2028 ) 2029 ), # whoops sorry bill 2030 RemoveGloves(), 2031 DelayOld(2000), 2032 AnalyticsScreen('Tutorial Section 5'), 2033 Text( 2034 bs.Lstr( 2035 resource=f'{self._r}.phrase14Text', 2036 subs=[ 2037 ( 2038 '${NAME}', 2039 bs.Lstr( 2040 resource=f'{self._r}.randomName4Text' 2041 ), 2042 ) 2043 ], 2044 ) 2045 ), # you can pick up and throw things such as chuck here 2046 SpawnSpaz( 2047 0, 2048 (-4.0, 4.3, -2.5), 2049 make_current=True, 2050 flash=False, 2051 angle=90, 2052 ), 2053 SpawnSpaz( 2054 1, 2055 (5, 0, -1.0), 2056 relative_to=0, 2057 make_current=False, 2058 color=(0.4, 1.0, 0.7), 2059 name=bs.Lstr(resource=f'{self._r}.randomName4Text'), 2060 ), 2061 DelayOld(1000), 2062 Celebrate('left', 1, duration=1000), 2063 Move(1, 0.2), 2064 DelayOld(2000), 2065 PickUp(), 2066 DelayOld(200), 2067 Move(0.5, 1.0), 2068 DelayOld(1200), 2069 PickUp(), 2070 Move(0, 0), 2071 DelayOld(1000), 2072 Celebrate('left'), 2073 DelayOld(1500), 2074 Move(0, -1.0), 2075 DelayOld(800), 2076 Move(0, 0), 2077 DelayOld(800), 2078 SpawnSpaz( 2079 0, 2080 (1.5, 4.3, -4.0), 2081 make_current=True, 2082 flash=False, 2083 angle=0, 2084 ), 2085 AnalyticsScreen('Tutorial Section 6'), 2086 Text( 2087 bs.Lstr(resource=f'{self._r}.phrase15Text') 2088 ), # lastly there's bombs 2089 DelayOld(1900), 2090 Text( 2091 bs.Lstr(resource=f'{self._r}.phrase16Text') 2092 ), # throwing bombs takes practice 2093 DelayOld(2000), 2094 Bomb(), 2095 Move(-0.1, -0.1), 2096 DelayOld(100), 2097 Move(0, 0), 2098 DelayOld(500), 2099 DelayOld(1000), 2100 Bomb(), 2101 DelayOld(2000), 2102 Text( 2103 bs.Lstr(resource=f'{self._r}.phrase17Text') 2104 ), # not a very good throw 2105 DelayOld(3000), 2106 Text( 2107 bs.Lstr(resource=f'{self._r}.phrase18Text') 2108 ), # moving helps you get distance 2109 DelayOld(1000), 2110 Bomb(), 2111 DelayOld(500), 2112 Move(-0.3, 0), 2113 DelayOld(100), 2114 Move(-0.6, 0), 2115 DelayOld(100), 2116 Move(-1, 0), 2117 DelayOld(800), 2118 Bomb(), 2119 DelayOld(400), 2120 Move(0, -0.1), 2121 DelayOld(100), 2122 Move(0, 0), 2123 DelayOld(2500), 2124 Text( 2125 bs.Lstr(resource=f'{self._r}.phrase19Text') 2126 ), # jumping helps you get height 2127 DelayOld(2000), 2128 Bomb(), 2129 DelayOld(500), 2130 Move(1, 0), 2131 DelayOld(300), 2132 Jump(release_delay=250), 2133 DelayOld(500), 2134 Jump(release_delay=250), 2135 DelayOld(550), 2136 Jump(release_delay=250), 2137 DelayOld(160), 2138 Punch(), 2139 DelayOld(500), 2140 Move(0, -0.1), 2141 DelayOld(100), 2142 Move(0, 0), 2143 DelayOld(2000), 2144 Text( 2145 bs.Lstr(resource=f'{self._r}.phrase20Text') 2146 ), # whiplash your bombs 2147 DelayOld(1000), 2148 Bomb(release=False), 2149 DelayOld2(80), 2150 RunRelease(), 2151 BombRelease(), 2152 DelayOld2(620), 2153 MoveLR(0), 2154 DelayOld2(10), 2155 MoveLR(0), 2156 DelayOld2(40), 2157 MoveLR(0), 2158 DelayOld2(10), 2159 MoveLR(-0.0537431), 2160 MoveUD(0), 2161 DelayOld2(20), 2162 MoveLR(-0.262764), 2163 DelayOld2(20), 2164 MoveLR(-0.498062), 2165 DelayOld2(10), 2166 MoveLR(-0.639241), 2167 DelayOld2(20), 2168 MoveLR(-0.73336), 2169 DelayOld2(10), 2170 MoveLR(-0.843165), 2171 MoveUD(-0.0352794), 2172 DelayOld2(30), 2173 MoveLR(-1), 2174 DelayOld2(10), 2175 MoveUD(-0.0588092), 2176 DelayOld2(10), 2177 MoveUD(-0.160772), 2178 DelayOld2(20), 2179 MoveUD(-0.286264), 2180 DelayOld2(20), 2181 MoveUD(-0.427442), 2182 DelayOld2(10), 2183 MoveUD(-0.623524), 2184 DelayOld2(20), 2185 MoveUD(-0.843135), 2186 DelayOld2(10), 2187 MoveUD(-1), 2188 DelayOld2(40), 2189 MoveLR(-0.890225), 2190 DelayOld2(10), 2191 MoveLR(-0.670614), 2192 DelayOld2(20), 2193 MoveLR(-0.435316), 2194 DelayOld2(20), 2195 MoveLR(-0.184332), 2196 DelayOld2(10), 2197 MoveLR(0.00390637), 2198 DelayOld2(20), 2199 MoveLR(0.223518), 2200 DelayOld2(10), 2201 MoveLR(0.388226), 2202 DelayOld2(20), 2203 MoveLR(0.560778), 2204 DelayOld2(20), 2205 MoveLR(0.717643), 2206 DelayOld2(10), 2207 MoveLR(0.890194), 2208 DelayOld2(20), 2209 MoveLR(1), 2210 DelayOld2(30), 2211 MoveUD(-0.968627), 2212 DelayOld2(20), 2213 MoveUD(-0.898038), 2214 DelayOld2(10), 2215 MoveUD(-0.741172), 2216 DelayOld2(20), 2217 MoveUD(-0.498032), 2218 DelayOld2(20), 2219 MoveUD(-0.247047), 2220 DelayOld2(10), 2221 MoveUD(0.00393689), 2222 DelayOld2(20), 2223 MoveUD(0.239235), 2224 DelayOld2(20), 2225 MoveUD(0.458846), 2226 DelayOld2(10), 2227 MoveUD(0.70983), 2228 DelayOld2(30), 2229 MoveUD(1), 2230 DelayOld2(10), 2231 MoveLR(0.827448), 2232 DelayOld2(10), 2233 MoveLR(0.678426), 2234 DelayOld2(20), 2235 MoveLR(0.396069), 2236 DelayOld2(10), 2237 MoveLR(0.0980255), 2238 DelayOld2(20), 2239 MoveLR(-0.160802), 2240 DelayOld2(20), 2241 MoveLR(-0.388256), 2242 DelayOld2(10), 2243 MoveLR(-0.545122), 2244 DelayOld2(30), 2245 MoveLR(-0.73336), 2246 DelayOld2(10), 2247 MoveLR(-0.945128), 2248 DelayOld2(10), 2249 MoveLR(-1), 2250 DelayOld2(50), 2251 MoveUD(0.960814), 2252 DelayOld2(20), 2253 MoveUD(0.890225), 2254 DelayOld2(10), 2255 MoveUD(0.749046), 2256 DelayOld2(20), 2257 MoveUD(0.623554), 2258 DelayOld2(20), 2259 MoveUD(0.498062), 2260 DelayOld2(10), 2261 MoveUD(0.34904), 2262 DelayOld2(20), 2263 MoveUD(0.239235), 2264 DelayOld2(20), 2265 MoveUD(0.137272), 2266 DelayOld2(10), 2267 MoveUD(0.0117801), 2268 DelayOld2(20), 2269 MoveUD(-0.0117496), 2270 DelayOld2(10), 2271 MoveUD(-0.0274361), 2272 DelayOld2(90), 2273 MoveUD(-0.0352794), 2274 Run(release=False), 2275 Jump(release=False), 2276 Delay(80), 2277 Punch(release=False), 2278 DelayOld2(60), 2279 MoveLR(-0.968657), 2280 DelayOld2(20), 2281 MoveLR(-0.835322), 2282 DelayOld2(10), 2283 MoveLR(-0.70983), 2284 JumpRelease(), 2285 DelayOld2(30), 2286 MoveLR(-0.592181), 2287 MoveUD(-0.0588092), 2288 DelayOld2(10), 2289 MoveLR(-0.490219), 2290 MoveUD(-0.0744957), 2291 DelayOld2(10), 2292 MoveLR(-0.41963), 2293 DelayOld2(20), 2294 MoveLR(0), 2295 MoveUD(0), 2296 DelayOld2(20), 2297 MoveUD(0), 2298 PunchRelease(), 2299 RunRelease(), 2300 DelayOld(500), 2301 Move(0, -0.1), 2302 DelayOld(100), 2303 Move(0, 0), 2304 DelayOld(2000), 2305 AnalyticsScreen('Tutorial Section 7'), 2306 Text( 2307 bs.Lstr(resource=f'{self._r}.phrase21Text') 2308 ), # timing your bombs can be tricky 2309 Move(-1, 0), 2310 DelayOld(1000), 2311 Move(0, -0.1), 2312 DelayOld(100), 2313 Move(0, 0), 2314 SpawnSpaz( 2315 0, 2316 (-0.7, 4.3, -3.9), 2317 make_current=True, 2318 flash=False, 2319 angle=-30, 2320 ), 2321 SpawnSpaz( 2322 1, 2323 (6.5, 0, -0.75), 2324 relative_to=0, 2325 make_current=False, 2326 color=(0.3, 0.8, 1.0), 2327 name=bs.Lstr(resource=f'{self._r}.randomName5Text'), 2328 ), 2329 DelayOld2(1000), 2330 Move(-1, 0), 2331 DelayOld2(1800), 2332 Bomb(), 2333 Move(0, 0), 2334 DelayOld2(300), 2335 Move(1, 0), 2336 DelayOld2(600), 2337 Jump(), 2338 DelayOld2(150), 2339 Punch(), 2340 DelayOld2(800), 2341 Move(-1, 0), 2342 DelayOld2(1000), 2343 Move(0, 0), 2344 DelayOld2(1500), 2345 Text(bs.Lstr(resource=f'{self._r}.phrase22Text')), # dang 2346 Delay(1500), 2347 Text(''), 2348 Delay(200), 2349 Text( 2350 bs.Lstr(resource=f'{self._r}.phrase23Text') 2351 ), # try cooking off 2352 Delay(1500), 2353 Bomb(), 2354 Delay(800), 2355 Move(1, 0.12), 2356 Delay(1100), 2357 Jump(), 2358 Delay(100), 2359 Punch(), 2360 Delay(100), 2361 Move(0, -0.1), 2362 Delay(100), 2363 Move(0, 0), 2364 Delay(2000), 2365 Text( 2366 bs.Lstr(resource=f'{self._r}.phrase24Text') 2367 ), # hooray nicely cooked 2368 Celebrate(), 2369 DelayOld(2000), 2370 KillSpaz(1), 2371 Text(''), 2372 Move(0.5, -0.5), 2373 DelayOld(1000), 2374 Move(0, -0.1), 2375 DelayOld(100), 2376 Move(0, 0), 2377 DelayOld(1000), 2378 AnalyticsScreen('Tutorial Section 8'), 2379 Text( 2380 bs.Lstr(resource=f'{self._r}.phrase25Text') 2381 ), # well that's just about it 2382 DelayOld(2000), 2383 Text( 2384 bs.Lstr(resource=f'{self._r}.phrase26Text') 2385 ), # go get em tiger 2386 DelayOld(2000), 2387 Text( 2388 bs.Lstr(resource=f'{self._r}.phrase27Text') 2389 ), # remember you training 2390 DelayOld(3000), 2391 Text( 2392 bs.Lstr(resource=f'{self._r}.phrase28Text') 2393 ), # well maybe 2394 DelayOld(1600), 2395 Text( 2396 bs.Lstr(resource=f'{self._r}.phrase29Text') 2397 ), # good luck 2398 Celebrate('right', duration=10000), 2399 DelayOld(1000), 2400 AnalyticsScreen('Tutorial Complete'), 2401 End(), 2402 ] 2403 ) 2404 2405 except Exception: 2406 logging.exception('Error running tutorial.') 2407 2408 # If we read some, exec them. 2409 if self._entries: 2410 self._run_next_entry() 2411 # Otherwise try again in a few seconds. 2412 else: 2413 self._read_entries_timer = bs.Timer( 2414 3.0, bs.WeakCall(self._read_entries) 2415 ) 2416 2417 def _run_next_entry(self) -> None: 2418 while self._entries: 2419 entry = self._entries.popleft() 2420 try: 2421 result = entry.run(self) 2422 except Exception: 2423 result = None 2424 logging.exception('Error in tutorial _run_next_entry.') 2425 2426 # If the entry returns an int value, set a timer; 2427 # otherwise just keep going. 2428 if result is not None: 2429 self._entry_timer = bs.Timer( 2430 result / 1000.0, bs.WeakCall(self._run_next_entry) 2431 ) 2432 return 2433 2434 # Done with these entries.. start over soon. 2435 self._read_entries_timer = bs.Timer( 2436 1.0, bs.WeakCall(self._read_entries) 2437 ) 2438 2439 def _update_skip_votes(self) -> None: 2440 count = sum(1 for player in self.players if player.pressed) 2441 assert self._skip_count_text 2442 self._skip_count_text.text = ( 2443 bs.Lstr( 2444 resource=f'{self._r}.skipVoteCountText', 2445 subs=[ 2446 ('${COUNT}', str(count)), 2447 ('${TOTAL}', str(len(self.players))), 2448 ], 2449 ) 2450 if count > 0 2451 else '' 2452 ) 2453 if ( 2454 count >= len(self.players) 2455 and self.players 2456 and not self._have_skipped 2457 ): 2458 bs.increment_analytics_count('Tutorial skip') 2459 bs.set_analytics_screen('Tutorial Skip') 2460 self._have_skipped = True 2461 bs.getsound('swish').play() 2462 # self._skip_count_text.text = self._r.skippingText 2463 self._skip_count_text.text = bs.Lstr( 2464 resource=f'{self._r}.skippingText' 2465 ) 2466 assert self._skip_text 2467 self._skip_text.text = '' 2468 self.end() 2469 2470 def _player_pressed_button(self, player: Player) -> None: 2471 # Special case: if there's only one player, we give them a 2472 # warning on their first press (some players were thinking the 2473 # on-screen guide meant they were supposed to press something). 2474 if len(self.players) == 1 and not self._issued_warning: 2475 self._issued_warning = True 2476 assert self._skip_text 2477 self._skip_text.text = bs.Lstr( 2478 resource=f'{self._r}.skipConfirmText' 2479 ) 2480 self._skip_text.color = (1, 1, 1) 2481 self._skip_text.scale = 1.3 2482 incr = 50 2483 t = incr 2484 for _i in range(6): 2485 bs.timer( 2486 t / 1000.0, 2487 bs.Call(setattr, self._skip_text, 'color', (1, 0.5, 0.1)), 2488 ) 2489 t += incr 2490 bs.timer( 2491 t / 1000.0, 2492 bs.Call(setattr, self._skip_text, 'color', (1, 1, 0)), 2493 ) 2494 t += incr 2495 bs.timer(6.0, bs.WeakCall(self._revert_confirm)) 2496 return 2497 2498 player.pressed = True 2499 2500 # test... 2501 if not all(self.players): 2502 logging.error( 2503 'Nonexistent player in _player_pressed_button:' 2504 ' %s: we are %s', 2505 [str(p) for p in self.players], 2506 player, 2507 ) 2508 2509 self._update_skip_votes() 2510 2511 def _revert_confirm(self) -> None: 2512 assert self._skip_text 2513 self._skip_text.text = bs.Lstr( 2514 resource=f'{self._r}.toSkipPressAnythingText' 2515 ) 2516 self._skip_text.color = (1, 1, 1) 2517 self._issued_warning = False 2518 2519 @override 2520 def on_player_join(self, player: Player) -> None: 2521 super().on_player_join(player) 2522 2523 # We just wanna know if this player presses anything. 2524 player.assigninput( 2525 ( 2526 bs.InputType.JUMP_PRESS, 2527 bs.InputType.PUNCH_PRESS, 2528 bs.InputType.BOMB_PRESS, 2529 bs.InputType.PICK_UP_PRESS, 2530 ), 2531 bs.Call(self._player_pressed_button, player), 2532 ) 2533 2534 @override 2535 def on_player_leave(self, player: Player) -> None: 2536 if not all(self.players): 2537 logging.error( 2538 'Nonexistent player in on_player_leave: %s: we are %s', 2539 [str(p) for p in self.players], 2540 player, 2541 ) 2542 super().on_player_leave(player) 2543 # our leaving may influence the vote total needed/etc 2544 self._update_skip_votes()
Units of execution wrangled by a bascenev1.Session.
Category: Gameplay Classes
Examples of Activities include games, score-screens, cutscenes, etc. A bascenev1.Session has one 'current' Activity at any time, though their existence can overlap during transitions.
189 def __init__(self, settings: dict | None = None): 190 from bascenev1lib.maps import Rampage 191 192 if settings is None: 193 settings = {} 194 super().__init__(settings) 195 self.current_spaz: Spaz | None = None 196 self._benchmark_type = getattr(bs.getsession(), 'benchmark_type', None) 197 self.last_start_time: int | None = None 198 self.cycle_times: list[int] = [] 199 self.allow_pausing = True 200 self.allow_kick_idle_players = False 201 self._issued_warning = False 202 self._map_type = Rampage 203 self._map_type.preload() 204 self._jump_button_tex = bs.gettexture('buttonJump') 205 self._pick_up_button_tex = bs.gettexture('buttonPickUp') 206 self._bomb_button_tex = bs.gettexture('buttonBomb') 207 self._punch_button_tex = bs.gettexture('buttonPunch') 208 self._r = 'tutorial' 209 self._have_skipped = False 210 self.stick_image_position_x = self.stick_image_position_y = 0.0 211 self.spawn_sound = bs.getsound('spawn') 212 self.map: bs.Map | None = None 213 self.text: bs.Node | None = None 214 self._skip_text: bs.Node | None = None 215 self._skip_count_text: bs.Node | None = None 216 self._scale: float | None = None 217 self._stick_base_position: tuple[float, float] = (0.0, 0.0) 218 self._stick_nub_position: tuple[float, float] = (0.0, 0.0) 219 self._stick_base_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 220 self._stick_nub_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0) 221 self._time: int = -1 222 self.punch_image_color = (1.0, 1.0, 1.0) 223 self.punch_image: bs.Node | None = None 224 self.bomb_image: bs.Node | None = None 225 self.jump_image: bs.Node | None = None 226 self.pickup_image: bs.Node | None = None 227 self._stick_base_image: bs.Node | None = None 228 self._stick_nub_image: bs.Node | None = None 229 self.bomb_image_color = (1.0, 1.0, 1.0) 230 self.pickup_image_color = (1.0, 1.0, 1.0) 231 self.control_ui_nodes: list[bs.Node] = [] 232 self.spazzes: dict[int, Spaz] = {} 233 self.jump_image_color = (1.0, 1.0, 1.0) 234 self._entries: deque[Any] = deque() 235 self._read_entries_timer: bs.Timer | None = None 236 self._entry_timer: bs.Timer | None = None
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.
Whether idle players can potentially be kicked (should not happen in menus/etc).
238 @override 239 def on_transition_in(self) -> None: 240 super().on_transition_in() 241 bs.setmusic(bs.MusicType.CHAR_SELECT, continuous=True) 242 self.map = self._map_type()
Called when the Activity is first becoming visible.
Upon this call, the Activity should fade in backgrounds, start playing music, etc. It does not yet have access to players or teams, however. They remain owned by the previous Activity up until bascenev1.Activity.on_begin() is called.
244 @override 245 def on_begin(self) -> None: 246 super().on_begin() 247 248 bs.set_analytics_screen('Tutorial Start') 249 bs.increment_analytics_count('Tutorial start') 250 251 if bool(False): 252 # Buttons on top. 253 text_y = 140 254 buttons_y = 250 255 else: 256 # Buttons on bottom. 257 text_y = 260 258 buttons_y = 160 259 260 # Need different versions of this: taps/buttons/keys. 261 self.text = bs.newnode( 262 'text', 263 attrs={ 264 'text': '', 265 'scale': 1.9, 266 'position': (0, text_y), 267 'maxwidth': 500, 268 'flatness': 0.0, 269 'shadow': 0.5, 270 'h_align': 'center', 271 'v_align': 'center', 272 'v_attach': 'center', 273 }, 274 ) 275 276 # Need different versions of this: taps/buttons/keys. 277 txt = ( 278 bs.Lstr(resource=f'{self._r}.cpuBenchmarkText') 279 if self._benchmark_type == 'cpu' 280 else bs.Lstr(resource=f'{self._r}.toSkipPressAnythingText') 281 ) 282 t = self._skip_text = bs.newnode( 283 'text', 284 attrs={ 285 'text': txt, 286 'maxwidth': 900, 287 'scale': 1.1, 288 'vr_depth': 100, 289 'position': (0, 30), 290 'h_align': 'center', 291 'v_align': 'center', 292 'v_attach': 'bottom', 293 }, 294 ) 295 bs.animate(t, 'opacity', {1.0: 0.0, 2.0: 0.7}) 296 self._skip_count_text = bs.newnode( 297 'text', 298 attrs={ 299 'text': '', 300 'scale': 1.4, 301 'vr_depth': 90, 302 'position': (0, 70), 303 'h_align': 'center', 304 'v_align': 'center', 305 'v_attach': 'bottom', 306 }, 307 ) 308 309 ouya = False 310 311 self._scale = scale = 0.6 312 center_offs = 130.0 * scale 313 offs = 65.0 * scale 314 position = (0, buttons_y) 315 image_size = 90.0 * scale 316 image_size_2 = 220.0 * scale 317 nub_size = 110.0 * scale 318 p = (position[0] + center_offs, position[1] - offs) 319 320 def _sc(r: float, g: float, b: float) -> tuple[float, float, float]: 321 return 0.6 * r, 0.6 * g, 0.6 * b 322 323 self.jump_image_color = c = _sc(0.4, 1, 0.4) 324 self.jump_image = bs.newnode( 325 'image', 326 attrs={ 327 'texture': self._jump_button_tex, 328 'absolute_scale': True, 329 'vr_depth': -20, 330 'position': p, 331 'scale': (image_size, image_size), 332 'color': c, 333 }, 334 ) 335 p = (position[0] + center_offs - offs, position[1]) 336 self.punch_image_color = c = ( 337 _sc(0.2, 0.6, 1) if ouya else _sc(1, 0.7, 0.3) 338 ) 339 self.punch_image = bs.newnode( 340 'image', 341 attrs={ 342 'texture': bs.gettexture('buttonPunch'), 343 'absolute_scale': True, 344 'vr_depth': -20, 345 'position': p, 346 'scale': (image_size, image_size), 347 'color': c, 348 }, 349 ) 350 p = (position[0] + center_offs + offs, position[1]) 351 self.bomb_image_color = c = _sc(1, 0.3, 0.3) 352 self.bomb_image = bs.newnode( 353 'image', 354 attrs={ 355 'texture': bs.gettexture('buttonBomb'), 356 'absolute_scale': True, 357 'vr_depth': -20, 358 'position': p, 359 'scale': (image_size, image_size), 360 'color': c, 361 }, 362 ) 363 p = (position[0] + center_offs, position[1] + offs) 364 self.pickup_image_color = c = ( 365 _sc(1, 0.8, 0.3) if ouya else _sc(0.5, 0.5, 1) 366 ) 367 self.pickup_image = bs.newnode( 368 'image', 369 attrs={ 370 'texture': bs.gettexture('buttonPickUp'), 371 'absolute_scale': True, 372 'vr_depth': -20, 373 'position': p, 374 'scale': (image_size, image_size), 375 'color': c, 376 }, 377 ) 378 379 self._stick_base_position = p = (position[0] - center_offs, position[1]) 380 self._stick_base_image_color = c2 = (0.25, 0.25, 0.25, 1.0) 381 self._stick_base_image = bs.newnode( 382 'image', 383 attrs={ 384 'texture': bs.gettexture('nub'), 385 'absolute_scale': True, 386 'vr_depth': -40, 387 'position': p, 388 'scale': (image_size_2, image_size_2), 389 'color': c2, 390 }, 391 ) 392 self._stick_nub_position = p = (position[0] - center_offs, position[1]) 393 self._stick_nub_image_color = c3 = (0.4, 0.4, 0.4, 1.0) 394 self._stick_nub_image = bs.newnode( 395 'image', 396 attrs={ 397 'texture': bs.gettexture('nub'), 398 'absolute_scale': True, 399 'position': p, 400 'scale': (nub_size, nub_size), 401 'color': c3, 402 }, 403 ) 404 self.control_ui_nodes = [ 405 self.jump_image, 406 self.punch_image, 407 self.bomb_image, 408 self.pickup_image, 409 self._stick_base_image, 410 self._stick_nub_image, 411 ] 412 for n in self.control_ui_nodes: 413 n.opacity = 0.0 414 self._read_entries()
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.
416 def set_stick_image_position(self, x: float, y: float) -> None: 417 # Clamp this to a circle. 418 len_squared = x * x + y * y 419 if len_squared > 1.0: 420 length = math.sqrt(len_squared) 421 mult = 1.0 / length 422 x *= mult 423 y *= mult 424 425 self.stick_image_position_x = x 426 self.stick_image_position_y = y 427 offs = 50.0 428 assert self._scale is not None 429 p = [ 430 self._stick_nub_position[0] + x * offs * self._scale, 431 self._stick_nub_position[1] + y * offs * self._scale, 432 ] 433 c = list(self._stick_nub_image_color) 434 if abs(x) > 0.1 or abs(y) > 0.1: 435 c[0] *= 2.0 436 c[1] *= 4.0 437 c[2] *= 2.0 438 assert self._stick_nub_image is not None 439 self._stick_nub_image.position = p 440 self._stick_nub_image.color = c 441 c = list(self._stick_base_image_color) 442 if abs(x) > 0.1 or abs(y) > 0.1: 443 c[0] *= 1.5 444 c[1] *= 1.5 445 c[2] *= 1.5 446 assert self._stick_base_image is not None 447 self._stick_base_image.color = c
2519 @override 2520 def on_player_join(self, player: Player) -> None: 2521 super().on_player_join(player) 2522 2523 # We just wanna know if this player presses anything. 2524 player.assigninput( 2525 ( 2526 bs.InputType.JUMP_PRESS, 2527 bs.InputType.PUNCH_PRESS, 2528 bs.InputType.BOMB_PRESS, 2529 bs.InputType.PICK_UP_PRESS, 2530 ), 2531 bs.Call(self._player_pressed_button, player), 2532 )
Called when a new bascenev1.Player has joined the Activity.
(including the initial set of Players)
2534 @override 2535 def on_player_leave(self, player: Player) -> None: 2536 if not all(self.players): 2537 logging.error( 2538 'Nonexistent player in on_player_leave: %s: we are %s', 2539 [str(p) for p in self.players], 2540 player, 2541 ) 2542 super().on_player_leave(player) 2543 # our leaving may influence the vote total needed/etc 2544 self._update_skip_votes()
Called when a bascenev1.Player is leaving the Activity.
Inherited Members
- bascenev1._activity.Activity
- settings_raw
- teams
- players
- announce_player_deaths
- is_joining_activity
- use_fixed_vr_overlay
- slow_motion
- inherits_slow_motion
- inherits_music
- inherits_vr_camera_offset
- inherits_vr_overlay_center
- inherits_tint
- allow_mid_activity_joins
- transition_time
- 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_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