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