def handlemessage(self, msg: Any) -> Any: if isinstance(msg, playerspaz.PlayerSpazDeathMessage): player = msg.spaz.getplayer() if player is None: ba.print_error('FIXME: getplayer() should no longer ' 'ever be returning None.') return if not player: return self.stats.player_was_killed(player) ba.timer(0.1, self._checkroundover) elif isinstance(msg, ba.PlayerScoredMessage): self._score += msg.score self._update_scores() elif isinstance(msg, spazbot.SpazBotDeathMessage): pts, importance = msg.badguy.get_death_points(msg.how) target: Optional[Sequence[float]] if msg.killerplayer: try: assert msg.badguy.node target = msg.badguy.node.position except Exception: ba.print_exception() target = None try: self.stats.player_scored(msg.killerplayer, pts, target=target, kill=True, screenmessage=False, importance=importance) ba.playsound(self._dingsound if importance == 1 else self._dingsoundhigh, volume=0.6) except Exception as exc: print('EXC on last-stand SpazBotDeathMessage', exc) # Normally we pull scores from the score-set, but if there's no # player lets be explicit. else: self._score += pts self._update_scores() else: super().handlemessage(msg)
def _on_egg_player_collide(self) -> None: if not self.has_ended(): egg_node, playernode = ba.get_collision_info( 'source_node', 'opposing_node') if egg_node is not None and playernode is not None: egg = egg_node.getdelegate() assert isinstance(egg, Egg) spaz = playernode.getdelegate() assert isinstance(spaz, playerspaz.PlayerSpaz) player = (spaz.getplayer() if hasattr(spaz, 'getplayer') else None) if player and egg: player.team.gamedata['score'] += 1 # Displays a +1 (and adds to individual player score in # teams mode). self.stats.player_scored(player, 1, screenmessage=False) if self._max_eggs < 5: self._max_eggs += 1.0 elif self._max_eggs < 10: self._max_eggs += 0.5 elif self._max_eggs < 30: self._max_eggs += 0.3 self._update_scoreboard() ba.playsound(self._collect_sound, 0.5, position=egg.node.position) # Create a flash. light = ba.newnode('light', attrs={ 'position': egg_node.position, 'height_attenuated': False, 'radius': 0.1, 'color': (1, 1, 0) }) ba.animate(light, 'intensity', { 0: 0, 0.1: 1.0, 0.2: 0 }, loop=False) ba.timer(0.200, light.delete) egg.handlemessage(ba.DieMessage())
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, FlagPickedUpMessage): assert isinstance(msg.flag, FootballFlag) try: msg.flag.last_holding_player = msg.node.getdelegate( PlayerSpaz, True).getplayer(Player, True) except ba.NotFoundError: pass msg.flag.held_count += 1 elif isinstance(msg, FlagDroppedMessage): assert isinstance(msg.flag, FootballFlag) msg.flag.held_count -= 1 # Respawn dead players if they're still in the game. elif isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) self.respawn_player(msg.getplayer(Player)) # Respawn dead flags. elif isinstance(msg, FlagDiedMessage): if not self.has_ended(): self._flag_respawn_timer = ba.Timer(3.0, self._spawn_flag) self._flag_respawn_light = ba.NodeActor( ba.newnode('light', attrs={ 'position': self._flag_spawn_pos, 'height_attenuated': False, 'radius': 0.15, 'color': (1.0, 1.0, 0.3) })) assert self._flag_respawn_light.node ba.animate(self._flag_respawn_light.node, 'intensity', { 0.0: 0, 0.25: 0.15, 0.5: 0 }, loop=True) ba.timer(3.0, self._flag_respawn_light.node.delete) else: # Augment standard behavior. super().handlemessage(msg)
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.PlayerDiedMessage): ba.TeamGameActivity.handlemessage(self, msg) player = msg.getplayer(Player) self.respawn_player(player) killer = msg.getkillerplayer(Player) if killer is None: return # handle team-kills if killer.team is player.team: # in free-for-all, killing yourself loses you a point if isinstance(self.session, ba.FreeForAllSession): new_score = player.team.score - 1 new_score = max(0, new_score) player.team.score = new_score # in teams-mode it gives a point to the other team else: ba.playsound(self._ding_sound) for team in self.teams: if team is not killer.team: team.score += 1 # killing someone on another team nets a kill else: killer.team.score += 1 ba.playsound(self._ding_sound) # in FFA show our score since its hard to find on # the scoreboard assert killer.actor is not None # noinspection PyUnresolvedReferences killer.actor.set_score_text(str(killer.team.score) + '/' + str(self._score_to_win), color=killer.team.color, flash=True) self._update_scoreboard() # if someone has won, set a timer to end shortly # (allows the dust to clear and draws to occur if # deaths are close enough) if any(team.score >= self._score_to_win for team in self.teams): ba.timer(0.5, self.end_game) else: ba.TeamGameActivity.handlemessage(self, msg)
def _on_achievements_press(self) -> None: # pylint: disable=cyclic-import from bastd.ui import achievements account_state = _ba.get_v1_account_state() account_type = (_ba.get_v1_account_type() if account_state == 'signed_in' else 'unknown') # for google play we use the built-in UI; otherwise pop up our own if account_type == 'Google Play': ba.timer(0.15, ba.Call(_ba.show_online_score_ui, 'achievements'), timetype=ba.TimeType.REAL) elif account_type != 'unknown': assert self._achievements_button is not None achievements.AchievementsWindow( position=self._achievements_button.get_screen_space_center()) else: print('ERROR: unknown account type in on_achievements_press:', account_type)
def _sign_out_press(self) -> None: if ba.app.accounts_v2.have_primary_credentials(): ba.app.accounts_v2.set_primary_credentials(None) else: _ba.sign_out_v1() cfg = ba.app.config # Also take note that its our *explicit* intention to not be # signed in at this point (affects v1 accounts). cfg['Auto Account State'] = 'signed_out' cfg.commit() ba.buttonwidget(edit=self._sign_out_button, label=ba.Lstr(resource=self._r + '.signingOutText')) # Speed UI updates along. ba.timer(0.1, ba.WeakCall(self._update), timetype=ba.TimeType.REAL)
def on_begin(self) -> None: from bastd.maps import TowerD # There's a player-wall on the tower-d level to prevent # players from getting up on the stairs.. we wanna kill that. gamemap = self.map assert isinstance(gamemap, TowerD) gamemap.player_wall.delete() super().on_begin() self._update_scoreboard() self._update_timer = ba.Timer(0.25, self._update, repeat=True) self._countdown = OnScreenCountdown(60, endcall=self.end_game) ba.timer(4.0, self._countdown.start) self._bots = spazbot.BotSet() # Spawn evil bunny in co-op only. if isinstance(self.session, ba.CoopSession) and self._pro_mode: self._spawn_evil_bunny()
def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, ba.DieMessage): if not self._dying and self.node: self._dying = True if msg.immediate: self.node.delete() else: ba.animate( self.node, 'project_scale', { 0.0: 1 * self._project_scale, 0.6: 1.2 * self._project_scale }) ba.animate(self.node, 'opacity', {0.0: 1, 0.3: 0}) ba.animate(self.node, 'trail_opacity', {0.0: 1, 0.6: 0}) ba.timer(0.7, self.node.delete) return None return super().handlemessage(msg)
def _capture_button(self, pos: Tuple[float, float], color: Tuple[float, float, float], texture: ba.Texture, button: str, scale: float = 1.0, message: ba.Lstr = None, message2: ba.Lstr = None, maxwidth: float = 80.0) -> ba.Widget: if message is None: message = ba.Lstr(resource=self._r + '.pressAnyButtonText') base_size = 79 btn = ba.buttonwidget(parent=self._root_widget, position=(pos[0] - base_size * 0.5 * scale, pos[1] - base_size * 0.5 * scale), autoselect=True, size=(base_size * scale, base_size * scale), texture=texture, label='', color=color) # Make this in a timer so that it shows up on top of all other buttons. def doit() -> None: uiscale = 0.9 * scale txt = ba.textwidget(parent=self._root_widget, position=(pos[0] + 0.0 * scale, pos[1] - 58.0 * scale), color=(1, 1, 1, 0.3), size=(0, 0), h_align='center', v_align='center', scale=uiscale, text=self.get_control_value_name(button), maxwidth=maxwidth) self._textwidgets[button] = txt ba.buttonwidget(edit=btn, on_activate_call=ba.Call(AwaitGamepadInputWindow, self._input, button, self._gamepad_event, message, message2)) ba.timer(0, doit, timetype=ba.TimeType.REAL) return btn
def on_begin(self) -> None: super().on_begin() self._start_time = ba.time() self.setup_standard_time_limit(self._time_limit) self.setup_standard_powerup_drops() if self._solo_mode: self._vs_text = ba.NodeActor( ba.newnode('text', attrs={ 'position': (0, 105), 'h_attach': 'center', 'h_align': 'center', 'maxwidth': 200, 'shadow': 0.5, 'vr_depth': 390, 'scale': 0.6, 'v_attach': 'bottom', 'color': (0.8, 0.8, 0.3, 1.0), 'text': ba.Lstr(resource='vsText') })) # If balance-team-lives is on, add lives to the smaller team until # total lives match. if (isinstance(self.session, ba.DualTeamSession) and self._balance_total_lives and self.teams[0].players and self.teams[1].players): if self._get_total_team_lives( self.teams[0]) < self._get_total_team_lives(self.teams[1]): lesser_team = self.teams[0] greater_team = self.teams[1] else: lesser_team = self.teams[1] greater_team = self.teams[0] add_index = 0 while (self._get_total_team_lives(lesser_team) < self._get_total_team_lives(greater_team)): lesser_team.players[add_index].lives += 1 add_index = (add_index + 1) % len(lesser_team.players) self._update_icons() # We could check game-over conditions at explicit trigger points, # but lets just do the simple thing and poll it. ba.timer(1.0, self._update, repeat=True)
def __init__(self, position: Sequence[float] = (0, 1, 0), lifetime: float = 0.5, highlight: bool = True): super().__init__() # array of nodes that received health kit self.cured_nodes: List[ba.Node] = [] self.area_material: ba.Material = ba.Material() shared = SharedObjects.get() self.area_material.add_actions( conditions=(('they_have_material', shared.player_material)), actions=(('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), ('call', 'at_connect', self._touch_handler))) # the area itself... self.node: ba.Node = ba.newnode('region', attrs={ 'type': 'sphere', 'scale': (2, 2, 2), 'position': position, 'materials': [self.area_material] }) ba.timer(lifetime, self.node.delete) # highlight the treatment area if highlight: self.area_highlight: ba.Node = ba.newnode( 'light', attrs={ 'color': (1, 1, 1), 'radius': 0.25, 'position': position, 'volume_intensity_scale': 1.0 }) # a little beautiful animation ba.animate(self.area_highlight, 'intensity', { 0: 0, lifetime / 2: 1.0, lifetime: 0 })
def explode(self) -> None: """Blows up the bomb if it has not yet done so.""" if self._exploded: return self._exploded = True if self.node: blast = Blast(position=self.node.position, velocity=self.node.velocity, blast_radius=self.blast_radius, blast_type=self.bomb_type, source_player=ba.existing(self._source_player), hit_type=self.hit_type, hit_subtype=self.hit_subtype).autoretain() for callback in self._explode_callbacks: callback(self, blast) # We blew up so we need to go away. # NOTE TO SELF: do we actually need this delay? ba.timer(0.001, ba.WeakCall(self.handlemessage, ba.DieMessage()))
def on_player_leave(self, player: Player) -> None: super().on_player_leave(player) player.icons = [] # Remove us from spawn-order. if self._solo_mode: if player in player.team.spawn_order: player.team.spawn_order.remove(player) # Update icons in a moment since our team will be gone from the # list then. ba.timer(0, self._update_icons) # If the player to leave was the last in spawn order and had # their final turn currently in-progress, mark the survival time # for their team. if self._get_total_team_lives(player.team) == 0: assert self._start_time is not None player.team.survival_seconds = int(ba.time() - self._start_time)
def _do_soundtracks(self) -> None: # pylint: disable=cyclic-import from bastd.ui.soundtrack import browser as stb # We require disk access for soundtracks; # if we don't have it, request it. if not _ba.have_permission(ba.Permission.STORAGE): ba.playsound(ba.getsound('ding')) ba.screenmessage(ba.Lstr(resource='storagePermissionAccessText'), color=(0.5, 1, 0.5)) ba.timer(1.0, ba.Call(_ba.request_permission, ba.Permission.STORAGE), timetype=ba.TimeType.REAL) return self._save_state() ba.containerwidget(edit=self._root_widget, transition='out_left') ba.app.main_menu_window = (stb.SoundtrackBrowserWindow( origin_widget=self._soundtrack_button).get_root_widget())
def _preload2() -> None: # FIXME: Could integrate these loads with the classes that use them # so they don't have to redundantly call the load # (even if the actual result is cached). for mname in ["powerup", "powerupSimple"]: ba.getmodel(mname) for tname in [ "powerupBomb", "powerupSpeed", "powerupPunch", "powerupIceBombs", "powerupStickyBombs", "powerupShield", "powerupImpactBombs", "powerupHealth" ]: ba.gettexture(tname) for sname in [ "powerup01", "boxDrop", "boxingBell", "scoreHit01", "scoreHit02", "dripity", "spawn", "gong" ]: ba.getsound(sname) from bastd.actor import bomb bomb.get_factory() ba.timer(0.1, _preload3)
def _preload2() -> None: # FIXME: Could integrate these loads with the classes that use them # so they don't have to redundantly call the load # (even if the actual result is cached). for mname in ['powerup', 'powerupSimple']: ba.getmodel(mname) for tname in [ 'powerupBomb', 'powerupSpeed', 'powerupPunch', 'powerupIceBombs', 'powerupStickyBombs', 'powerupShield', 'powerupImpactBombs', 'powerupHealth' ]: ba.gettexture(tname) for sname in [ 'powerup01', 'boxDrop', 'boxingBell', 'scoreHit01', 'scoreHit02', 'dripity', 'spawn', 'gong' ]: ba.getsound(sname) from bastd.actor.bomb import BombFactory BombFactory.get() ba.timer(0.1, _preload3)
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, PlayerSpazDeathMessage): # Augment standard behavior. super().handlemessage(msg) self.respawn_player(msg.spaz.player) elif isinstance(msg, stdflag.FlagDeathMessage): assert isinstance(msg.flag, CTFFlag) ba.timer(0.1, ba.Call(self._spawn_flag_for_team, msg.flag.team)) elif isinstance(msg, stdflag.FlagPickedUpMessage): # Store the last player to hold the flag for scoring purposes. assert isinstance(msg.flag, CTFFlag) msg.flag.last_player_to_hold = msg.node.getdelegate().getplayer() msg.flag.held_count += 1 msg.flag.reset_return_times() elif isinstance(msg, stdflag.FlagDroppedMessage): # Store the last player to hold the flag for scoring purposes. assert isinstance(msg.flag, CTFFlag) msg.flag.held_count -= 1 else: super().handlemessage(msg)
def explode(self) -> None: """Blows up the bomb if it has not yet done so.""" if self._exploded: return self._exploded = True activity = self.getactivity() if activity is not None and self.node: blast = Blast(position=self.node.position, velocity=self.node.velocity, blast_radius=self.blast_radius, blast_type=self.bomb_type, source_player=self.source_player, hit_type=self.hit_type, hit_subtype=self.hit_subtype).autoretain() for callback in self._explode_callbacks: callback(self, blast) # we blew up so we need to go away # FIXME; was there a reason we need this delay? ba.timer(0.001, ba.WeakCall(self.handlemessage, ba.DieMessage()))
def handlemessage(self, msg: Any) -> Any: # pylint: disable=too-many-branches if __debug__: self._handlemessage_sanity_check() if isinstance(msg, ba.PowerupAcceptMessage): factory = get_factory() assert self.node if self.poweruptype == 'health': ba.playsound(factory.health_powerup_sound, 3, position=self.node.position) ba.playsound(factory.powerup_sound, 3, position=self.node.position) self._powersgiven = True self.handlemessage(ba.DieMessage()) elif isinstance(msg, _TouchedMessage): if not self._powersgiven: node = ba.get_collision_info('opposing_node') if node: node.handlemessage( ba.PowerupMessage(self.poweruptype, source_node=self.node)) elif isinstance(msg, ba.DieMessage): if self.node: if msg.immediate: self.node.delete() else: ba.animate(self.node, 'model_scale', {0: 1, 0.1: 0}) ba.timer(0.1, self.node.delete) elif isinstance(msg, ba.OutOfBoundsMessage): self.handlemessage(ba.DieMessage()) elif isinstance(msg, ba.HitMessage): # Don't die on punches (that's annoying). if msg.hit_type != 'punch': self.handlemessage(ba.DieMessage()) else: super().handlemessage(msg)
def _drop_powerups(self, standard_points: bool = False, poweruptype: str = None) -> None: """Generic powerup drop.""" if standard_points: spawnpoints = self.map.powerup_spawn_points for i, _point in enumerate(spawnpoints): ba.timer(1.0 + i * 0.5, ba.Call(self._drop_powerup, i, poweruptype)) else: point = (self._powerup_center[0] + random.uniform( -1.0 * self._powerup_spread[0], 1.0 * self._powerup_spread[0]), self._powerup_center[1], self._powerup_center[2] + random.uniform( -self._powerup_spread[1], self._powerup_spread[1])) # Drop one random one somewhere. PowerupBox( position=point, poweruptype=PowerupBoxFactory.get().get_random_powerup_type( excludetypes=self._exclude_powerups)).autoretain()
def __init__(self, tab: GatherTab, scrollwidget: ba.Widget, tab_button: ba.Widget, width: float): self._tab = weakref.ref(tab) self._scrollwidget = scrollwidget self._tab_button = tab_button self._columnwidget = ba.columnwidget(parent=self._scrollwidget, border=2, margin=0, left_border=10) ba.widget(edit=self._columnwidget, up_widget=tab_button) self._width = width self._last_selected_host: Optional[Dict[str, Any]] = None self._update_timer = ba.Timer(1.0, ba.WeakCall(self.update), timetype=ba.TimeType.REAL, repeat=True) # Go ahead and run a few *almost* immediately so we don't # have to wait a second. self.update() ba.timer(0.25, ba.WeakCall(self.update), timetype=ba.TimeType.REAL)
def _second_portal_teleportation(self): """Teleportation of a node that entered the second portal.""" node = ba.getcollision().opposingnode name = node.getname() if self.already_teleported.get(name): return def wrapper(nodename): self.already_teleported[nodename] = False hold_node = node.hold_node node.handlemessage(ba.StandMessage(position=self.first_node.position)) if hold_node: self._second_portal_handler(hold_node, offset=(0, 1, 0)) node.hold_node = hold_node self.already_teleported[name] = True ba.timer(1, ba.Call(wrapper, name))
def _on_egg_player_collide(self) -> None: if self.has_ended(): return collision = ba.getcollision() # Be defensive here; we could be hitting the corpse of a player # who just left/etc. try: egg = collision.sourcenode.getdelegate(Egg, True) player = collision.opposingnode.getdelegate(PlayerSpaz, True).getplayer( Player, True) except ba.NotFoundError: return player.team.score += 1 # Displays a +1 (and adds to individual player score in # teams mode). self.stats.player_scored(player, 1, screenmessage=False) if self._max_eggs < 5: self._max_eggs += 1.0 elif self._max_eggs < 10: self._max_eggs += 0.5 elif self._max_eggs < 30: self._max_eggs += 0.3 self._update_scoreboard() ba.playsound(self._collect_sound, 0.5, position=egg.node.position) # Create a flash. light = ba.newnode('light', attrs={ 'position': egg.node.position, 'height_attenuated': False, 'radius': 0.1, 'color': (1, 1, 0) }) ba.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.2: 0}, loop=False) ba.timer(0.200, light.delete) egg.handlemessage(ba.DieMessage())
def _update(self): if not self.target: del self # commit suicide because we have no goal in our existing :( return d = ba.Vec3(self.target.position) - ba.Vec3(self.position) if d.length() < 0.1: self._blast() del self return d = d.normalized() * 0.04 from math import sin, cos self.position = (self.position[0] + d.x + sin(ba.time() * 2) * 0.03, self.position[1] + d.y, self.position[2] + d.z + cos(ba.time() * 2) * 0.03) self._sparkle() ba.timer(0.001, ba.WeakCall(self._update))
def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, ba.PowerupAcceptMessage): factory = PowerupBoxFactory.get() assert self.node if self.poweruptype == 'health': ba.playsound(factory.health_powerup_sound, 3, position=self.node.position) ba.playsound(factory.powerup_sound, 3, position=self.node.position) self._powersgiven = True self.handlemessage(ba.DieMessage()) elif isinstance(msg, _TouchedMessage): if not self._powersgiven: node = ba.getcollision().opposingnode node.handlemessage( ba.PowerupMessage(self.poweruptype, sourcenode=self.node)) elif isinstance(msg, ba.DieMessage): if self.node: if msg.immediate: self.node.delete() else: ba.animate(self.node, 'model_scale', {0: 1, 0.1: 0}) ba.timer(0.1, self.node.delete) elif isinstance(msg, ba.OutOfBoundsMessage): self.handlemessage(ba.DieMessage()) elif isinstance(msg, ba.HitMessage): # Don't die on punches (that's annoying). if msg.hit_type != 'punch': self.handlemessage(ba.DieMessage()) else: return super().handlemessage(msg) return None
def arm(self, actor: stdbomb.Bomb): factory = stdbomb.BombFactory.get() elon_mine_lit_tex = ba.gettexture('circleNoAlpha') elon_mine_tex = ba.gettexture('achievementCrossHair') actor.texture_sequence = ba.newnode('texture_sequence', owner=actor.node, attrs={ 'rate': 30, 'input_textures': (elon_mine_lit_tex, elon_mine_tex) }) ba.timer(0.5, actor.texture_sequence.delete) ba.playsound(ba.getsound('activateBeep'), position=actor.node.position) actor.aim = AutoAim(actor.node, actor.owner) # we now make it explodable. ba.timer( 0.25, ba.WeakCall(actor._add_material, factory.land_mine_blast_material)) actor.texture_sequence.connectattr('output_texture', actor.node, 'color_texture')
def _drop_bomb_cluster(self) -> None: # Random note: code like this is a handy way to plot out extents # and debug things. loc_test = False if loc_test: ba.newnode('locator', attrs={'position': (8, 6, -5.5)}) ba.newnode('locator', attrs={'position': (8, 6, -2.3)}) ba.newnode('locator', attrs={'position': (-7.3, 6, -5.5)}) ba.newnode('locator', attrs={'position': (-7.3, 6, -2.3)}) # Drop several bombs in series. delay = 0.0 for _i in range(random.randrange(1, 3)): # Drop them somewhere within our bounds with velocity pointing # toward the opposite side. pos = (-7.3 + 15.3 * random.random(), 11, -5.5 + 2.1 * random.random()) dropdir = (-1.0 if pos[0] > 0 else 1.0) vel = ((-5.0 + random.random() * 30.0) * dropdir, -4.0, 0) ba.timer(delay, ba.Call(self._drop_bomb, pos, vel)) delay += 0.1 self._set_meteor_timer()
def handle_player_died(self) -> None: """Well poo; our player died.""" if not self.node: return if self._show_death: ba.animate( self.node, 'opacity', { 0.00: 1.0, 0.05: 0.0, 0.10: 1.0, 0.15: 0.0, 0.20: 1.0, 0.25: 0.0, 0.30: 1.0, 0.35: 0.0, 0.40: 1.0, 0.45: 0.0, 0.50: 1.0, 0.55: 0.2 }) lives = self._player.lives if lives == 0: ba.timer(0.6, self.update_for_lives)
def _preload1() -> None: """Pre-load some assets a second or two into the main menu. Helps avoid hitches later on. """ for mname in [ 'plasticEyesTransparent', 'playerLineup1Transparent', 'playerLineup2Transparent', 'playerLineup3Transparent', 'playerLineup4Transparent', 'angryComputerTransparent', 'scrollWidgetShort', 'windowBGBlotch' ]: ba.getmodel(mname) for tname in ['playerLineup', 'lock']: ba.gettexture(tname) for tex in [ 'iconRunaround', 'iconOnslaught', 'medalComplete', 'medalBronze', 'medalSilver', 'medalGold', 'characterIconMask' ]: ba.gettexture(tex) ba.gettexture('bg') from bastd.actor.powerupbox import PowerupBoxFactory PowerupBoxFactory.get() ba.timer(0.1, _preload2)
def _die(self, immediate: bool = False) -> None: session = self._session() if session is None and self.node: # If session is gone, our node should be too, # since it was part of the session's scene. # Let's make sure that's the case. # (since otherwise we have no way to kill it) ba.print_error('got None session on Background _die' ' (and node still exists!)') elif session is not None: with ba.Context(session): if not self._dying and self.node: self._dying = True if immediate: self.node.delete() else: ba.animate(self.node, 'opacity', { 0.0: 1.0, self.fade_time: 0.0 }, loop=False) ba.timer(self.fade_time + 0.1, self.node.delete)