Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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())
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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()
Ejemplo n.º 8
0
 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)
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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()))
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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())
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
 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)
Ejemplo n.º 18
0
    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()))
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
    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()
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
    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))
Ejemplo n.º 23
0
    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())
Ejemplo n.º 24
0
            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))
Ejemplo n.º 25
0
    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
Ejemplo n.º 26
0
    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')
Ejemplo n.º 27
0
    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()
Ejemplo n.º 28
0
 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)
Ejemplo n.º 29
0
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)
Ejemplo n.º 30
0
 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)