コード例 #1
0
    def handlemessage(self, msg: Any) -> Any:
        if isinstance(msg, ba.PlayerDiedMessage):

            # Augment standard behavior.
            super().handlemessage(msg)
            player: Player = msg.getplayer(Player)

            player.lives -= 1
            if player.lives < 0:
                ba.print_error(
                    "Got lives < 0 in Elim; this shouldn't happen. duo: True")
                player.lives = 0

            # If we have any icons, update their state.
            for icon in player.icons:
                icon.handle_player_died()

            # Play big death sound on our last death
            # or for every one in solo mode.
            if player.lives == 0:
                ba.playsound(SpazFactory.get().single_player_death_sound)

            # If we hit zero lives, we're dead (and our team might be too).
            if player.lives == 0:
                # If the whole team is now dead, mark their survival time.
                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)

            # In solo, put ourself at the back of the spawn order.
            if self._duo_mode:
                player.team.spawn_order.remove(player)
                player.team.spawn_order.append(player)
コード例 #2
0
    def equip_shields(self, decay: bool = False) -> None:
        """
        Give this spaz a nice energy shield.
        """

        if not self.node:
            ba.print_error('Can\'t equip shields; no node.')
            return

        factory = SpazFactory.get()
        if self.shield is None:
            self.shield = ba.newnode('shield',
                                     owner=self.node,
                                     attrs={
                                         'color':
                                         ((0 + random.random() * 6.5),
                                          (0 + random.random() * 6.5),
                                          (0 + random.random() * 6.5)),
                                         'radius':
                                         1.3
                                     })
            self.node.connectattr('position_center', self.shield, 'position')
            #ba.animate_array(self.shield, 'color', 3,{0:(1,0,0),0.2:(1,0.5,0),0.4:(1,1,0),0.6:(0,1,0),0.8:(0,1,1),1.0:(0,0,1),1.2:(1,0,0)},True)
        self.shield_hitpoints = self.shield_hitpoints_max = 650
        self.shield_decay_rate = factory.shield_decay_rate if decay else 0
        self.shield.hurt = 0
        ba.playsound(factory.shield_up_sound, 1.0, position=self.node.position)

        if self.shield_decay_rate > 0:
            self.shield_decay_timer = ba.Timer(0.5,
                                               ba.WeakCall(self.shield_decay),
                                               repeat=True)
            # So user can see the decay.
            self.shield.always_show_health_bar = True
コード例 #3
0
ファイル: race.py プロジェクト: Awesome-Logic/ballistica
 def handlemessage(self, msg: Any) -> Any:
     if isinstance(msg, PlayerSpazDeathMessage):
         # Augment default behavior.
         super().handlemessage(msg)
         player = msg.spaz.getplayer()
         if not player:
             ba.print_error('got no player in PlayerSpazDeathMessage')
             return
         if not player.gamedata['finished']:
             self.respawn_player(player, respawn_time=1)
     else:
         super().handlemessage(msg)
コード例 #4
0
    def _refresh(self) -> None:
        chars: Optional[list[str]] = None
        if self._mode in ['normal', 'caps']:
            chars = list(self._chars)
            if self._mode == 'caps':
                chars = [c.upper() for c in chars]
            ba.buttonwidget(edit=self._shift_button,
                            color=self._key_color_lit
                            if self._mode == 'caps' else self._key_color_dark,
                            label=charstr(SpCh.SHIFT),
                            on_activate_call=self._shift)
            ba.buttonwidget(edit=self._num_mode_button,
                            label='123#&*',
                            on_activate_call=self._num_mode)
            ba.buttonwidget(edit=self._emoji_button,
                            color=self._key_color_dark,
                            label=charstr(SpCh.LOGO_FLAT),
                            on_activate_call=self._next_mode)
        else:
            if self._mode == 'num':
                chars = list(self._keyboard.nums)
            else:
                chars = list(self._keyboard.pages[self._mode])
            ba.buttonwidget(edit=self._shift_button,
                            color=self._key_color_dark,
                            label='',
                            on_activate_call=self._null_press)
            ba.buttonwidget(edit=self._num_mode_button,
                            label='abc',
                            on_activate_call=self._abc_mode)
            ba.buttonwidget(edit=self._emoji_button,
                            color=self._key_color_dark,
                            label=charstr(SpCh.LOGO_FLAT),
                            on_activate_call=self._next_mode)

        for i, btn in enumerate(self._char_keys):
            assert chars is not None
            have_char = True
            if i >= len(chars):
                # No such char.
                have_char = False
                pagename = self._mode
                ba.print_error(
                    f'Size of page "{pagename}" of keyboard'
                    f' "{self._keyboard.name}" is incorrect:'
                    f' {len(chars)} != {len(self._chars)}'
                    f' (size of default "normal" page)',
                    once=True)
            ba.buttonwidget(edit=btn,
                            label=chars[i] if have_char else ' ',
                            on_activate_call=ba.Call(
                                self._type_char,
                                chars[i] if have_char else ' '))
コード例 #5
0
    def _tick(self) -> None:

        # Give the chosen one points.
        player = self._get_chosen_one_player()
        if player is not None:

            # This shouldn't happen, but just in case.
            if not player.is_alive():
                ba.print_error('got dead player as chosen one in _tick')
                self._set_chosen_one_player(None)
            else:
                scoring_team = player.team
                assert self.stats
                self.stats.player_scored(player,
                                         3,
                                         screenmessage=False,
                                         display=False)

                scoring_team.gamedata['time_remaining'] = max(
                    0, scoring_team.gamedata['time_remaining'] - 1)

                # show the count over their head
                try:
                    if scoring_team.gamedata['time_remaining'] > 0:
                        if isinstance(player.actor, spaz.Spaz):
                            player.actor.set_score_text(
                                str(scoring_team.gamedata['time_remaining']))
                except Exception:
                    pass

                self._update_scoreboard()

                # announce numbers we have sounds for
                try:
                    ba.playsound(self._countdownsounds[
                        scoring_team.gamedata['time_remaining']])
                except Exception:
                    pass

                # Winner!
                if scoring_team.gamedata['time_remaining'] <= 0:
                    self.end_game()

        else:
            # (player is None)
            # This shouldn't happen, but just in case.
            # (Chosen-one player ceasing to exist should
            # trigger on_player_leave which resets chosen-one)
            if self._chosen_one_player is not None:
                ba.print_error('got nonexistent player as chosen one in _tick')
                self._set_chosen_one_player(None)
コード例 #6
0
    def handlemessage(self, msg: Any) -> Any:

        if isinstance(msg, ba.PlayerDiedMessage):
            #==
            losingPlayer = msg.getplayer(Player)
            if len(self.myPlayers) > 1:
                if self.playerFromName(self.myPlayers[self.count -
                                                      2]) == losingPlayer:
                    winningPlayer = self.playerFromName(
                        self.myPlayers[self.count - 1])
                else:
                    winningPlayer = self.playerFromName(
                        self.myPlayers[self.count - 2])
                if str(losingPlayer.getname()) in self.myPlayers:
                    self.myPlayers.remove(str(losingPlayer.getname()))
                if winningPlayer.team.survival_seconds <= losingPlayer.team.survival_seconds:
                    winningPlayer.team.survival_seconds = losingPlayer.team.survival_seconds + 1
                else:
                    winningPlayer.team.survival_seconds += 1
                winningPlayer.wins += 1
                if winningPlayer.is_alive() and not len(self.myPlayers) == 1:
                    winningPlayer.actor.handlemessage(
                        ba.DieMessage(immediate=True))
                self.count -= 1
                self.spawnPlayer()
            #==

            # Augment standard behavior.
            super().handlemessage(msg)

            player: Player = msg.getplayer(Player)

            player.lives -= 1
            if player.lives < 0:
                ba.print_error("Got lives < 0 in Elim; this shouldn't happen.")
                player.lives = 0

            # If we have any icons, update their state.

            # Play big death sound on our last death
            # or for every one in solo mode.
            if player.lives == 0:
                ba.playsound(SpazFactory.get().single_player_death_sound)

            # If we hit zero lives, we're dead (and our team might be too).
            if player.lives == 0:
                pass
            else:
                self.respawn_player(player)
コード例 #7
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)
コード例 #8
0
    def _handle_touching_own_flag(self, team: Team, connecting: bool) -> None:
        """Called when a player touches or stops touching their own team flag.

        We keep track of when each player is touching their own flag so we
        can award points when returned.
        """
        player: Optional[Player]
        try:
            player = ba.getcollision().sourcenode.getdelegate(
                PlayerSpaz, True).getplayer(Player, True)
        except ba.NotFoundError:
            # This can happen if the player leaves but his corpse touches/etc.
            player = None

        if player:
            player.touching_own_flag += (1 if connecting else -1)

        # If return-time is zero, just kill it immediately.. otherwise keep
        # track of touches and count down.
        if float(self.flag_touch_return_time) <= 0.0:
            assert team.flag is not None
            if (connecting and not team.home_flag_at_base
                    and team.flag.held_count == 0):
                self._award_players_touching_own_flag(team)
                ba.getcollision().opposingnode.handlemessage(ba.DieMessage())

        # Takes a non-zero amount of time to return.
        else:
            if connecting:
                team.flag_return_touches += 1
                if team.flag_return_touches == 1:
                    team.touch_return_timer = ba.Timer(
                        0.1,
                        call=ba.Call(self._touch_return_update, team),
                        repeat=True)
                    team.touch_return_timer_ticking = None
            else:
                team.flag_return_touches -= 1
                if team.flag_return_touches == 0:
                    team.touch_return_timer = None
                    team.touch_return_timer_ticking = None
            if team.flag_return_touches < 0:
                ba.print_error('CTF flag_return_touches < 0')
コード例 #9
0
ファイル: capturetheflag.py プロジェクト: bseditor/ballistica
    def _handle_hit_own_flag(self, team: ba.Team, val: int) -> None:
        """
        keep track of when each player is touching their
        own flag so we can award points when returned
        """
        srcnode = ba.get_collision_info('source_node')
        assert isinstance(srcnode, (ba.Node, type(None)))
        player = self._player_from_node(srcnode)
        if player:
            player.gamedata['touching_own_flag'] += (1 if val else -1)

        # If return-time is zero, just kill it immediately.. otherwise keep
        # track of touches and count down.
        if float(self.settings_raw['Flag Touch Return Time']) <= 0.0:
            if (not team.gamedata['home_flag_at_base']
                    and team.gamedata['flag'].held_count == 0):

                # Use a node message to kill the flag instead of just killing
                # our team's. (avoids redundantly killing new flags if
                # multiple body parts generate callbacks in one step).
                node = ba.get_collision_info('opposing_node')
                if node:
                    self._award_players_touching_own_flag(team)
                    node.handlemessage(ba.DieMessage())

        # Takes a non-zero amount of time to return.
        else:
            if val:
                team.gamedata['flag_return_touches'] += 1
                if team.gamedata['flag_return_touches'] == 1:
                    team.gamedata['touch_return_timer'] = ba.Timer(
                        0.1,
                        call=ba.Call(self._touch_return_update, team),
                        repeat=True)
                    team.gamedata['touch_return_timer_ticking'] = None
            else:
                team.gamedata['flag_return_touches'] -= 1
                if team.gamedata['flag_return_touches'] == 0:
                    team.gamedata['touch_return_timer'] = None
                    team.gamedata['touch_return_timer_ticking'] = None
            if team.gamedata['flag_return_touches'] < 0:
                ba.print_error(
                    "CTF: flag_return_touches < 0; this shouldn't happen.")
コード例 #10
0
    def handlemessage(self, msg: Any) -> Any:
        if isinstance(msg, playerspaz.PlayerSpazDeathMessage):

            # Augment standard behavior.
            super().handlemessage(msg)
            player = msg.spaz.player

            player.gamedata['lives'] -= 1
            if player.gamedata['lives'] < 0:
                ba.print_error(
                    "Got lives < 0 in Elim; this shouldn't happen. solo:" +
                    str(self._solo_mode))
                player.gamedata['lives'] = 0

            # If we have any icons, update their state.
            for icon in player.gamedata['icons']:
                icon.handle_player_died()

            # Play big death sound on our last death
            # or for every one in solo mode.
            if self._solo_mode or player.gamedata['lives'] == 0:
                ba.playsound(spaz.get_factory().single_player_death_sound)

            # If we hit zero lives, we're dead (and our team might be too).
            if player.gamedata['lives'] == 0:
                # If the whole team is now dead, mark their survival time.
                if self._get_total_team_lives(player.team) == 0:
                    assert self._start_time is not None
                    player.team.gamedata['survival_seconds'] = int(
                        ba.time() - self._start_time)
            else:
                # Otherwise, in regular mode, respawn.
                if not self._solo_mode:
                    self.respawn_player(player)

            # In solo, put ourself at the back of the spawn order.
            if self._solo_mode:
                player.team.gamedata['spawn_order'].remove(player)
                player.team.gamedata['spawn_order'].append(player)
コード例 #11
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)
コード例 #12
0
    def __init__(self,
                 text: Union[str, ba.Lstr],
                 position: Tuple[float, float] = (0.0, 0.0),
                 shiftposition: Tuple[float, float] = None,
                 shiftdelay: float = None,
                 lifespan: float = None,
                 flash: bool = True,
                 trail: bool = True,
                 h_align: str = 'center',
                 color: Sequence[float] = (0.9, 0.4, 0.0),
                 jitter: float = 0.0,
                 trailcolor: Sequence[float] = (1.0, 0.35, 0.1, 0.0),
                 scale: float = 1.0,
                 project_scale: float = 1.0,
                 tilt_translate: float = 0.0,
                 maxwidth: float = None):
        # pylint: disable=too-many-locals
        super().__init__()
        self._dying = False
        positionadjusted = (position[0], position[1] - 100)
        if shiftdelay is None:
            shiftdelay = 2.500
        if shiftdelay < 0.0:
            ba.print_error('got shiftdelay < 0')
            shiftdelay = 0.0
        self._project_scale = project_scale
        self.node = ba.newnode('text',
                               delegate=self,
                               attrs={
                                   'position':
                                   positionadjusted,
                                   'big':
                                   True,
                                   'text':
                                   text,
                                   'trail':
                                   trail,
                                   'vr_depth':
                                   0,
                                   'shadow':
                                   0.0 if trail else 0.3,
                                   'scale':
                                   scale,
                                   'maxwidth':
                                   maxwidth if maxwidth is not None else 0.0,
                                   'tilt_translate':
                                   tilt_translate,
                                   'h_align':
                                   h_align,
                                   'v_align':
                                   'center'
                               })

        # we never jitter in vr mode..
        if ba.app.vr_mode:
            jitter = 0.0

        # if they want jitter, animate its position slightly...
        if jitter > 0.0:
            self._jitter(positionadjusted, jitter * scale)

        # if they want shifting, move to the shift position and
        # then resume jittering
        if shiftposition is not None:
            positionadjusted2 = (shiftposition[0], shiftposition[1] - 100)
            ba.timer(
                shiftdelay,
                ba.WeakCall(self._shift, positionadjusted, positionadjusted2))
            if jitter > 0.0:
                ba.timer(
                    shiftdelay + 0.25,
                    ba.WeakCall(self._jitter, positionadjusted2,
                                jitter * scale))
        color_combine = ba.newnode('combine',
                                   owner=self.node,
                                   attrs={
                                       'input2': color[2],
                                       'input3': 1.0,
                                       'size': 4
                                   })
        if trail:
            trailcolor_n = ba.newnode('combine',
                                      owner=self.node,
                                      attrs={
                                          'size': 3,
                                          'input0': trailcolor[0],
                                          'input1': trailcolor[1],
                                          'input2': trailcolor[2]
                                      })
            trailcolor_n.connectattr('output', self.node, 'trailcolor')
            basemult = 0.85
            ba.animate(
                self.node, 'trail_project_scale', {
                    0: 0 * project_scale,
                    basemult * 0.201: 0.6 * project_scale,
                    basemult * 0.347: 0.8 * project_scale,
                    basemult * 0.478: 0.9 * project_scale,
                    basemult * 0.595: 0.93 * project_scale,
                    basemult * 0.748: 0.95 * project_scale,
                    basemult * 0.941: 0.95 * project_scale
                })
        if flash:
            mult = 2.0
            tm1 = 0.15
            tm2 = 0.3
            ba.animate(color_combine,
                       'input0', {
                           0: color[0] * mult,
                           tm1: color[0],
                           tm2: color[0] * mult
                       },
                       loop=True)
            ba.animate(color_combine,
                       'input1', {
                           0: color[1] * mult,
                           tm1: color[1],
                           tm2: color[1] * mult
                       },
                       loop=True)
            ba.animate(color_combine,
                       'input2', {
                           0: color[2] * mult,
                           tm1: color[2],
                           tm2: color[2] * mult
                       },
                       loop=True)
        else:
            color_combine.input0 = color[0]
            color_combine.input1 = color[1]
        color_combine.connectattr('output', self.node, 'color')
        ba.animate(self.node, 'project_scale', {
            0: 0,
            0.27: 1.05 * project_scale,
            0.3: 1 * project_scale
        })

        # if they give us a lifespan, kill ourself down the line
        if lifespan is not None:
            ba.timer(lifespan, ba.WeakCall(self.handlemessage,
                                           ba.DieMessage()))