def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.PlayerScoredMessage): self._score += msg.score self._update_scores() elif isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) self._a_player_has_been_killed = True # Respawn them shortly. player = msg.getplayer(Player) assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.respawn_icon = RespawnIcon(player, respawn_time) elif isinstance(msg, SpazBotDiedMessage): if msg.how is ba.DeathType.REACHED_GOAL: return None pts, importance = msg.spazbot.get_death_points(msg.how) if msg.killerplayer is not None: target: Optional[Sequence[float]] try: assert msg.spazbot is not None assert msg.spazbot.node target = msg.spazbot.node.position except Exception: ba.print_exception() target = None try: if msg.killerplayer: 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: ba.print_exception('Error on SpazBotDiedMessage') # 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: return super().handlemessage(msg) return None
def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._swipsound = ba.getsound("swip") self._tick_sound = ba.getsound('tick') self._countdownsounds = { 10: ba.getsound('announceTen'), 9: ba.getsound('announceNine'), 8: ba.getsound('announceEight'), 7: ba.getsound('announceSeven'), 6: ba.getsound('announceSix'), 5: ba.getsound('announceFive'), 4: ba.getsound('announceFour'), 3: ba.getsound('announceThree'), 2: ba.getsound('announceTwo'), 1: ba.getsound('announceOne') } self._flag_pos: Optional[Sequence[float]] = None self._flag_state: Optional[int] = None self._flag: Optional[stdflag.Flag] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[ReferenceType[ba.Team]] = None self._flag_region_material = ba.Material() self._flag_region_material.add_actions( conditions=("they_have_material", ba.sharedobj('player_material')), actions=(("modify_part_collision", "collide", True), ("modify_part_collision", "physical", False), ("call", "at_connect", ba.Call(self._handle_player_flag_region_collide, True)), ("call", "at_disconnect", ba.Call(self._handle_player_flag_region_collide, False))))
def final_celebrate(self) -> None: """Tell all bots in the set to stop what they were doing and celebrate. Use this when the bots have won a game. """ self._bot_update_timer = None # At this point stop doing anything but jumping and celebrating. for botlist in self._bot_lists: for bot in botlist: if bot: assert bot.node # (should exist if 'if bot' was True) bot.node.move_left_right = 0 bot.node.move_up_down = 0 ba.timer(0.5 * random.random(), ba.Call(bot.handlemessage, ba.CelebrateMessage())) jump_duration = random.randrange(400, 500) j = random.randrange(0, 200) for _i in range(10): bot.node.jump_pressed = True bot.node.jump_pressed = False j += jump_duration ba.timer(random.uniform(0.0, 1.0), ba.Call(bot.node.handlemessage, 'attack_sound')) ba.timer(random.uniform(1.0, 2.0), ba.Call(bot.node.handlemessage, 'attack_sound')) ba.timer(random.uniform(2.0, 3.0), ba.Call(bot.node.handlemessage, 'attack_sound'))
def _run_addr_fetch(self) -> None: try: # FIXME: Update this to work with IPv6. import socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect(('8.8.8.8', 80)) val = sock.getsockname()[0] sock.close() ba.pushcall( ba.Call( _safe_set_text, self._checking_state_text, val, ), from_other_thread=True, ) except Exception as exc: from efro.error import is_udp_network_error if is_udp_network_error(exc): ba.pushcall(ba.Call( _safe_set_text, self._checking_state_text, ba.Lstr(resource='gatherWindow.' 'noConnectionText'), False), from_other_thread=True) else: ba.pushcall(ba.Call( _safe_set_text, self._checking_state_text, ba.Lstr(resource='gatherWindow.' 'addressFetchErrorText'), False), from_other_thread=True) ba.pushcall(ba.Call(ba.print_error, 'error in AddrFetchThread: ' + str(exc)), from_other_thread=True)
def on_begin(self) -> None: ba.set_analytics_screen('Teams Score Screen') super().on_begin() height = 130 active_team_count = len(self.teams) vval = (height * active_team_count) / 2 - height / 2 i = 0 shift_time = 2.5 # Usually we say 'Best of 7', but if the language prefers we can say # 'First to 4'. session = self.session assert isinstance(session, ba.MultiTeamSession) if ba.app.lang.get_resource('bestOfUseFirstToInstead'): best_txt = ba.Lstr(resource='firstToSeriesText', subs=[('${COUNT}', str(session.get_series_length() / 2 + 1)) ]) else: best_txt = ba.Lstr(resource='bestOfSeriesText', subs=[('${COUNT}', str(session.get_series_length()))]) # ZoomText(best_txt, # position=(0, 175), # shiftposition=(-250, 175), # shiftdelay=2.5, # flash=False, # trail=False, # h_align='center', # scale=0.25, # color=(0.5, 0.5, 0.5, 1.0), # jitter=3.0).autoretain() for team in self.session.sessionteams: ba.timer( i * 0.15 + 0.15, ba.WeakCall(self._show_team_name, vval - i * height, team, i * 0.2, shift_time - (i * 0.150 + 0.150))) ba.timer(i * 0.150 + 0.5, ba.Call(ba.playsound, self._score_display_sound_small)) scored = (team is self._winner) delay = 0.2 if scored: delay = 1.2 ba.timer( i * 0.150 + 0.2, ba.WeakCall(self._show_team_old_score, vval - i * height, team, shift_time - (i * 0.15 + 0.2))) ba.timer(i * 0.15 + 1.5, ba.Call(ba.playsound, self._score_display_sound)) ba.timer( i * 0.150 + delay, ba.WeakCall(self._show_team_score, vval - i * height, team, scored, i * 0.2 + 0.1, shift_time - (i * 0.15 + delay))) i += 1 self.show_player_scores()
def __init__(self): self.Timer = ba.Timer(8, ba.Call(self.refreshStats), timetype=ba.TimeType.REAL, repeat=True) self.Timerr = ba.Timer(10, ba.Call(self.startThread), timetype=ba.TimeType.REAL, repeat=True)
def _handle_reached_end(self) -> None: spaz = ba.getcollision().opposingnode.getdelegate(SpazBot, True) if not spaz.is_alive(): return # Ignore bodies flying in. self._flawless = False pos = spaz.node.position ba.playsound(self._bad_guy_score_sound, position=pos) light = ba.newnode('light', attrs={ 'position': pos, 'radius': 0.5, 'color': (1, 0, 0) }) ba.animate(light, 'intensity', {0.0: 0, 0.1: 1, 0.5: 0}, loop=False) ba.timer(1.0, light.delete) spaz.handlemessage( ba.DieMessage(immediate=True, how=ba.DeathType.REACHED_GOAL)) if self._lives > 0: self._lives -= 1 if self._lives == 0: self._bots.stop_moving() self.continue_or_end_game() assert self._lives_text is not None assert self._lives_text.node self._lives_text.node.text = str(self._lives) delay = 0.0 def _safesetattr(node: ba.Node, attr: str, value: Any) -> None: if node: setattr(node, attr, value) for _i in range(4): ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (1, 0, 0, 1.0))) assert self._lives_bg is not None assert self._lives_bg.node ba.timer( delay, ba.Call(_safesetattr, self._lives_bg.node, 'opacity', 0.5)) delay += 0.125 ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (1.0, 1.0, 0.0, 1.0))) ba.timer( delay, ba.Call(_safesetattr, self._lives_bg.node, 'opacity', 1.0)) delay += 0.125 ba.timer( delay, ba.Call(_safesetattr, self._lives_text.node, 'color', (0.8, 0.8, 0.8, 1.0)))
def handlemessage(self, msg: Any) -> Any: """ handle high-level game messages """ if isinstance(msg, playerspaz.PlayerSpazDeathMessage): from bastd.actor import respawnicon # Respawn dead players. player = msg.spaz.player self.stats.player_was_killed(player) assert self.initial_player_info is not None respawn_time = 2.0 + len(self.initial_player_info) * 1.0 # Respawn them shortly. player.gamedata['respawn_timer'] = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.gamedata['respawn_icon'] = respawnicon.RespawnIcon( player, respawn_time) # Augment standard behavior. super().handlemessage(msg) elif isinstance(msg, spazbot.SpazBotDeathMessage): # Every time a bad guy dies, spawn a new one. ba.timer(3.0, ba.Call(self._spawn_bot, (type(msg.badguy)))) elif isinstance(msg, spazbot.SpazBotPunchedMessage): if self._preset in ['rookie', 'rookie_easy']: if msg.damage >= 500: self._award_achievement('Super Punch') elif self._preset in ['pro', 'pro_easy']: if msg.damage >= 1000: self._award_achievement('Super Mega Punch') # Respawn dead flags. elif isinstance(msg, stdflag.FlagDeathMessage): assert isinstance(msg.flag, FootballFlag) msg.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.25: 0.15, 0.5: 0 }, loop=True) ba.timer(3.0, self._flag_respawn_light.node.delete) else: super().handlemessage(msg)
def _config_value_editor( self, name: ba.Lstr, control: str, position: tuple[float, float], min_val: float = 0.0, max_val: float = 100.0, increment: float = 1.0, change_sound: bool = True, x_offset: float = 0.0, displayname: ba.Lstr = None) -> tuple[ba.Widget, ba.Widget]: if displayname is None: displayname = name ba.textwidget(parent=self._subcontainer, position=position, size=(100, 30), text=displayname, color=(0.8, 0.8, 0.8, 1.0), h_align='left', v_align='center', scale=1.0, maxwidth=280) self._textwidgets[control] = ba.textwidget( parent=self._subcontainer, position=(246.0 + x_offset, position[1]), size=(60, 28), editable=False, color=(0.3, 1.0, 0.3, 1.0), h_align='right', v_align='center', text=self._parent_window.get_control_value_name(control), padding=2) btn = ba.buttonwidget(parent=self._subcontainer, autoselect=True, position=(330 + x_offset, position[1] + 4), size=(28, 28), label='-', on_activate_call=ba.Call(self._inc, control, min_val, max_val, -increment), repeat=True, enable_sound=(change_sound is True)) btn2 = ba.buttonwidget(parent=self._subcontainer, autoselect=True, position=(380 + x_offset, position[1] + 4), size=(28, 28), label='+', on_activate_call=ba.Call( self._inc, control, min_val, max_val, increment), repeat=True, enable_sound=(change_sound is True)) return btn, btn2
def _set_tab(self, tab: str) -> None: if tab != 'my_replays': self._set_tab_replays(tab) return elif self._current_tab == tab: return uiscale = ba.app.ui.uiscale c_height = self._scroll_height - 20 b_width = 140 if uiscale is ba.UIScale.SMALL else 178 b_height = (82 if uiscale is ba.UIScale.SMALL else 80 if uiscale is ba.UIScale.MEDIUM else 106) b_space_extra = (0 if uiscale is ba.UIScale.SMALL else 2 if uiscale is ba.UIScale.MEDIUM else 3) btnv = (c_height - (48 if uiscale is ba.UIScale.SMALL else 55 if uiscale is ba.UIScale.MEDIUM else 50) - b_height) btnh = 40 tscl = 1.0 if uiscale is ba.UIScale.SMALL else 1.2 b_color = (0.6, 0.53, 0.63) b_textcolor = (0.75, 0.7, 0.8) self._set_tab_replays(tab) for child in self._tab_container.get_children(): if child and child.get_widget_type() == 'button': ba.buttonwidget(edit=child, position=(btnh, btnv), size=(b_width, b_height)) btnv -= b_height + b_space_extra self._upload_replays_button = ba.buttonwidget( parent=self._tab_container, size=(b_width, b_height), position=(btnh, btnv), button_type='square', color=b_color, textcolor=b_textcolor, on_activate_call=ba.Call(upload_replays, self), text_scale=tscl, label=ba.Lstr(value=Language.UPLOAD.value), autoselect=True) btnv -= b_height + b_space_extra self._save_replays_button = ba.buttonwidget( parent=self._tab_container, size=(b_width, b_height), position=(btnh, btnv), button_type='square', color=b_color, textcolor=b_textcolor, on_activate_call=ba.Call(save_replays), text_scale=tscl, label=ba.Lstr(value=Language.SAVE.value), autoselect=True)
def _on_favorites_rename_press(self) -> None: if self._favorite_selected is None: self._no_favorite_selected_error() return c_width = 600 c_height = 250 uiscale = ba.app.ui.uiscale self._favorite_rename_window = cnt = ba.containerwidget( scale=(1.8 if uiscale is ba.UIScale.SMALL else 1.55 if uiscale is ba.UIScale.MEDIUM else 1.0), size=(c_width, c_height), transition='in_scale') ba.textwidget(parent=cnt, size=(0, 0), h_align='center', v_align='center', text='Enter Name of Party', maxwidth=c_width * 0.8, position=(c_width * 0.5, c_height - 60)) self._party_rename_text = txt = ba.textwidget( parent=cnt, size=(c_width * 0.8, 40), h_align='left', v_align='center', text=ba.app.config['Saved Servers'][ self._favorite_selected]['name'], editable=True, description='Server name text', position=(c_width * 0.1, c_height - 140), autoselect=True, maxwidth=c_width * 0.7, max_chars=200) cbtn = ba.buttonwidget( parent=cnt, label=ba.Lstr(resource='cancelText'), on_activate_call=ba.Call( lambda c: ba.containerwidget(edit=c, transition='out_scale'), cnt), size=(180, 60), position=(30, 30), autoselect=True) okb = ba.buttonwidget(parent=cnt, label='Rename', size=(180, 60), position=(c_width - 230, 30), on_activate_call=ba.Call( self._rename_saved_party), autoselect=True) ba.widget(edit=cbtn, right_widget=okb) ba.widget(edit=okb, left_widget=cbtn) ba.textwidget(edit=txt, on_return_press_call=okb.activate) ba.containerwidget(edit=cnt, cancel_button=cbtn, start_button=okb)
def _on_my_replay_rename_press(self) -> None: if self._my_replay_selected is None: self._no_replay_selected_error() return c_width = 600 c_height = 250 uiscale = ba.app.ui.uiscale self._my_replays_rename_window = cnt = ba.containerwidget( scale=(1.8 if uiscale is ba.UIScale.SMALL else 1.55 if uiscale is ba.UIScale.MEDIUM else 1.0), size=(c_width, c_height), transition='in_scale') dname = self._get_replay_display_name(self._my_replay_selected) ba.textwidget(parent=cnt, size=(0, 0), h_align='center', v_align='center', text=ba.Lstr(resource=self._r + '.renameReplayText', subs=[('${REPLAY}', dname)]), maxwidth=c_width * 0.8, position=(c_width * 0.5, c_height - 60)) self._my_replay_rename_text = txt = ba.textwidget( parent=cnt, size=(c_width * 0.8, 40), h_align='left', v_align='center', text=dname, editable=True, description=ba.Lstr(resource=self._r + '.replayNameText'), position=(c_width * 0.1, c_height - 140), autoselect=True, maxwidth=c_width * 0.7, max_chars=200) cbtn = ba.buttonwidget( parent=cnt, label=ba.Lstr(resource='cancelText'), on_activate_call=ba.Call( lambda c: ba.containerwidget(edit=c, transition='out_scale'), cnt), size=(180, 60), position=(30, 30), autoselect=True) okb = ba.buttonwidget(parent=cnt, label=ba.Lstr(resource=self._r + '.renameText'), size=(180, 60), position=(c_width - 230, 30), on_activate_call=ba.Call( self._rename_my_replay, self._my_replay_selected), autoselect=True) ba.widget(edit=cbtn, right_widget=okb) ba.widget(edit=okb, left_widget=cbtn) ba.textwidget(edit=txt, on_return_press_call=okb.activate) ba.containerwidget(edit=cnt, cancel_button=cbtn, start_button=okb)
def _sync_target(self): try: bap.repo.sync() except Exception as e: ba.pushcall(ba.Call(ba.screenmessage, f"Error: {e}", color=(1, 0, 0)), from_other_thread=True) else: ba.pushcall(ba.Call(ba.screenmessage, "Done", color=(0, 1, 0)), from_other_thread=True) ba.pushcall(self._refresh, from_other_thread=True)
def run() -> None: if os.path.exists(src) and os.path.exists(dst): if not os.path.exists(dst + os.path.sep + os.path.basename(src)): try: shutil.copy(src, dst) except: pass # pass permission errors if callback is not None: ba.pushcall(ba.Call(callback, True), from_other_thread=True) elif callback is not None: ba.pushcall(ba.Call(callback, False), from_other_thread=True)
def handlemessage(self, msg: Any) -> Any: """ handle high-level game messages """ if isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) # Respawn them shortly. player = msg.getplayer(Player) assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.respawn_icon = RespawnIcon(player, respawn_time) elif isinstance(msg, SpazBotDiedMessage): # Every time a bad guy dies, spawn a new one. ba.timer(3.0, ba.Call(self._spawn_bot, (type(msg.spazbot)))) elif isinstance(msg, SpazBotPunchedMessage): if self._preset in ['rookie', 'rookie_easy']: if msg.damage >= 500: self._award_achievement('Super Punch') elif self._preset in ['pro', 'pro_easy']: if msg.damage >= 1000: self._award_achievement('Super Mega Punch') # Respawn dead flags. elif isinstance(msg, FlagDiedMessage): assert isinstance(msg.flag, FootballFlag) msg.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.25: 0.15, 0.5: 0 }, loop=True) ba.timer(3.0, self._flag_respawn_light.node.delete) else: return super().handlemessage(msg) return None
def _uninstall_target(): try: bap.uninstall(self.pkginfo.name) except Exception as e: ba.print_exception() ba.pushcall(ba.Call(ba.screenmessage, f'Error: {e}', color=(1, 0, 0)), from_other_thread=True) else: ba.pushcall(ba.Call(ba.screenmessage, 'Done', color=(0, 1, 0)), from_other_thread=True) if self._parent: self._parent._push_refresh()
def __init__(self, parent: ba.Widget, tabdefs: List[Tuple[T, ba.Lstr]], pos: Tuple[float, float], size: Tuple[float, float], on_select_call: Callable[[T], None] = None) -> None: if not tabdefs: raise ValueError('At least one tab def is required') self.tabs: Dict[T, Tab] = {} tab_pos_v = pos[1] tab_button_width = float(size[0]) / len(tabdefs) tab_spacing = (250.0 - tab_button_width) * 0.06 h = pos[0] for tab_id, tab_label in tabdefs: pos = (h + tab_spacing * 0.5, tab_pos_v) size = (tab_button_width - tab_spacing, 50.0) btn = ba.buttonwidget(parent=parent, position=pos, autoselect=True, button_type='tab', size=size, label=tab_label, enable_sound=False, on_activate_call=ba.Call( self._tick_and_call, on_select_call, tab_id)) h += tab_button_width self.tabs[tab_id] = Tab(button=btn, position=pos, size=size)
def update_scores(self) -> None: """ update scoreboard and check for winners """ # FIXME: tidy this up # pylint: disable=too-many-nested-blocks have_scoring_team = False win_score = self._score_to_win for team in [self.teams[0], self._bot_team]: assert team is not None assert self._scoreboard is not None self._scoreboard.set_team_value(team, team.gamedata['score'], win_score) if team.gamedata['score'] >= win_score: if not have_scoring_team: self.scoring_team = team if team is self._bot_team: self.continue_or_end_game() else: ba.setmusic(ba.MusicType.VICTORY) # Completion achievements. assert self._bot_team is not None if self._preset in ['rookie', 'rookie_easy']: self._award_achievement('Rookie Football Victory', sound=False) if self._bot_team.gamedata['score'] == 0: self._award_achievement( 'Rookie Football Shutout', sound=False) elif self._preset in ['pro', 'pro_easy']: self._award_achievement('Pro Football Victory', sound=False) if self._bot_team.gamedata['score'] == 0: self._award_achievement('Pro Football Shutout', sound=False) elif self._preset in ['uber', 'uber_easy']: self._award_achievement('Uber Football Victory', sound=False) if self._bot_team.gamedata['score'] == 0: self._award_achievement( 'Uber Football Shutout', sound=False) if (not self._player_has_dropped_bomb and not self._player_has_punched): self._award_achievement('Got the Moves', sound=False) self._bots.stop_moving() self.show_zoom_message(ba.Lstr(resource='victoryText'), scale=1.0, duration=4.0) self.celebrate(10.0) assert self._starttime_ms is not None self._final_time_ms = int( ba.time(timeformat=ba.TimeFormat.MILLISECONDS) - self._starttime_ms) self._time_text_timer = None assert (self._time_text_input is not None and self._time_text_input.node) self._time_text_input.node.timemax = ( self._final_time_ms) # FIXME: Does this still need to be deferred? ba.pushcall(ba.Call(self.do_end, 'victory'))
def handlemessage(self, msg: Any) -> Any: # Respawn dead players. if isinstance(msg, playerspaz.PlayerSpazDeathMessage): from bastd.actor import respawnicon # Augment standard behavior. super().handlemessage(msg) player = msg.spaz.getplayer() if not player: return self.stats.player_was_killed(player) # Respawn them shortly. assert self.initial_player_info is not None respawn_time = 2.0 + len(self.initial_player_info) * 1.0 player.gamedata['respawn_timer'] = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.gamedata['respawn_icon'] = respawnicon.RespawnIcon( player, respawn_time) # Whenever our evil bunny dies, respawn him and spew some eggs. elif isinstance(msg, spazbot.SpazBotDeathMessage): self._spawn_evil_bunny() assert msg.badguy.node pos = msg.badguy.node.position for _i in range(6): spread = 0.4 self._eggs.append( Egg(position=(pos[0] + random.uniform(-spread, spread), pos[1] + random.uniform(-spread, spread), pos[2] + random.uniform(-spread, spread)))) else: # Default handler. super().handlemessage(msg)
def __init__(self, button: str, ui: ba.Widget, settings: Dict[str, Any]): self._capture_button = button self._capture_key_ui = ui self._settings = settings width = 400 height = 150 super().__init__(root_widget=ba.containerwidget( size=(width, height), transition='in_right', scale=2.0 if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0)) ba.textwidget(parent=self._root_widget, position=(0, height - 60), size=(width, 25), text=ba.Lstr(resource='pressAnyKeyText'), h_align='center', v_align='top') self._counter = 5 self._count_down_text = ba.textwidget(parent=self._root_widget, h_align='center', position=(0, height - 110), size=(width, 25), color=(1, 1, 1, 0.3), text=str(self._counter)) self._decrement_timer: Optional[ba.Timer] = ba.Timer( 1.0, ba.Call(self._decrement), repeat=True, timetype=ba.TimeType.REAL) _ba.capture_keyboard_input(ba.WeakCall(self._button_callback))
def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ba.PlayerDiedMessage): super().handlemessage(msg) # Augment standard behavior. self.respawn_player(msg.getplayer(Player)) elif isinstance(msg, FlagDiedMessage): assert isinstance(msg.flag, CTFFlag) ba.timer(0.1, ba.Call(self._spawn_flag_for_team, msg.flag.team)) elif isinstance(msg, FlagPickedUpMessage): # Store the last player to hold the flag for scoring purposes. assert isinstance(msg.flag, CTFFlag) try: msg.flag.last_player_to_hold = msg.node.getdelegate( PlayerSpaz, True).getplayer(Player, True) except ba.NotFoundError: pass msg.flag.held_count += 1 msg.flag.reset_return_times() elif isinstance(msg, 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 _refresh_my_replays(self) -> None: assert self._columnwidget is not None for child in self._columnwidget.get_children(): child.delete() t_scale = 1.6 try: names = os.listdir(_ba.get_replays_dir()) # ignore random other files in there.. names = [n for n in names if n.endswith('.brp')] names.sort(key=lambda x: x.lower()) except Exception: ba.print_exception('Error listing replays dir.') names = [] assert self._my_replays_scroll_width is not None assert self._my_replays_watch_replay_button is not None for i, name in enumerate(names): txt = ba.textwidget( parent=self._columnwidget, size=(self._my_replays_scroll_width / t_scale, 30), selectable=True, color=(1.0, 1, 0.4) if name == '__lastReplay.brp' else (1, 1, 1), always_highlight=True, on_select_call=ba.Call(self._on_my_replay_select, name), on_activate_call=self._my_replays_watch_replay_button.activate, text=self._get_replay_display_name(name), h_align='left', v_align='center', corner_scale=t_scale, maxwidth=(self._my_replays_scroll_width / t_scale) * 0.93) if i == 0: ba.widget(edit=txt, up_widget=self._tab_buttons['my_replays'])
def handlemessage(self, msg: Any) -> Any: # Respawn dead players. if isinstance(msg, ba.PlayerDiedMessage): # Augment standard behavior. super().handlemessage(msg) # Respawn them shortly. player = msg.getplayer(Player) assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = ba.Timer( respawn_time, ba.Call(self.spawn_player_if_exists, player)) player.respawn_icon = RespawnIcon(player, respawn_time) # Whenever our evil bunny dies, respawn him and spew some eggs. elif isinstance(msg, SpazBotDiedMessage): self._spawn_evil_bunny() assert msg.spazbot.node pos = msg.spazbot.node.position for _i in range(6): spread = 0.4 self._eggs.append( Egg(position=(pos[0] + random.uniform(-spread, spread), pos[1] + random.uniform(-spread, spread), pos[2] + random.uniform(-spread, spread)))) else: # Default handler. return super().handlemessage(msg) return None
def on_transition_in(self) -> None: from bastd.actor.scoreboard import Scoreboard self.default_music = ba.MusicType.EPIC super().on_transition_in() ba.timer(1.3, ba.Call(ba.playsound, self._new_wave_sound)) self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'), score_split=0.5)
def _refresh_my_saved_parties(self) -> None: assert self._columnwidget is not None for child in self._columnwidget.get_children(): child.delete() t_scale = 1.6 config=ba.app.config if 'Saved Servers' in config: servers=config['Saved Servers'] else: servers = [] assert self._my_parties_scroll_width is not None assert self._my_saved_party_connect_button is not None for server in servers: txt = ba.textwidget( parent=self._columnwidget, size=(self._my_parties_scroll_width / t_scale, 30), selectable=True, color=(1.0, 1, 0.4) , always_highlight=True, on_select_call=ba.Call(self._on_my_saved_party_select, server), on_activate_call=self._my_saved_party_connect_button.activate, text=config['Saved Servers'][server]['name'] if config['Saved Servers'][server]['name']!='' else config['Saved Servers'][server]['addr']+" "+str(config['Saved Servers'][server]['port']), h_align='left', v_align='center', corner_scale=t_scale, maxwidth=(self._my_parties_scroll_width / t_scale) * 0.93)
def _second_portal_handler(self, node=None, offset=(0, 0, 0)): """Checking a node before teleporting in the second portal.""" if node is None: node = ba.getcollision().opposingnode name = node.getname() if self.already_teleported.get(name): return velocity = node.velocity node.position = (self.first_position[0] + offset[0], self.first_position[1] + offset[1], self.first_position[2] + offset[2]) def velocity_wrapper(): if node: node.velocity = velocity ba.timer(0.01, velocity_wrapper) self.already_teleported[name] = True def wrapper(nodename): self.already_teleported[nodename] = False ba.timer(1, ba.Call(wrapper, name))
def _drop_powerups(self, standard_points: bool = False, force_first: str = None) -> None: """Generic powerup drop.""" # If its been a minute since our last wave finished emerging, stop # giving out land-mine powerups. (prevents players from waiting # around for them on purpose and filling the map up) if ba.time() - self._last_wave_end_time > 60.0: extra_excludes = ['land_mines'] else: extra_excludes = [] if standard_points: points = self.map.powerup_spawn_points for i in range(len(points)): ba.timer( 1.0 + i * 0.5, ba.Call(self._drop_powerup, i, force_first if i == 0 else None)) else: pos = (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.. assert self._exclude_powerups is not None PowerupBox( position=pos, poweruptype=PowerupBoxFactory.get().get_random_powerup_type( excludetypes=self._exclude_powerups + extra_excludes)).autoretain()
def _on_my_saved_party_delete_press(self) -> None: from bastd.ui import confirm if self._my_saved_party_selected is None: self._no_saved_party_selected_error() return confirm.ConfirmWindow( "Confirm Delete ?", ba.Call(self._delete_saved_party, self._my_saved_party_selected), 450, 150)
def spawn_player(self, player: Player) -> ba.Actor: actor = self.spawn_player_spaz(player, self._get_spawn_point(player)) if not self._solo_mode: ba.timer(0.3, ba.Call(self._print_lives, player)) # If we have any icons, update their state. for icon in player.icons: icon.handle_player_spawned() return actor
def _activate(self) -> None: ba.playsound(ba.getsound('swish')) ba.timer(0.05, self._transition_out, timetype=ba.TimeType.REAL) delegate = self._getdelegate() if delegate is not None: # Call this in a timer so it doesn't interfere with us killing # our widgets and whatnot. call = ba.Call(delegate.popup_menu_selected_choice, self, self._current_choice) ba.timer(0, call, timetype=ba.TimeType.REAL)