예제 #1
0
    def _handle_score(self) -> None:
        """A point has been scored."""

        assert self._puck is not None
        assert self._score_regions is not None

        # Our puck might stick around for a second or two
        # we don't want it to be able to score again.
        if self._puck.scored:
            return

        region = ba.get_collision_info("source_node")
        index = 0
        for index in range(len(self._score_regions)):
            if region == self._score_regions[index].node:
                break

        for team in self.teams:
            if team.get_id() == index:
                scoring_team = team
                team.gamedata['score'] += 1

                # Tell all players to celebrate.
                for player in team.players:
                    if player.actor:
                        player.actor.handlemessage(ba.CelebrateMessage(2.0))

                # If we've got the player from the scoring team that last
                # touched us, give them points.
                if (scoring_team.get_id() in self._puck.last_players_to_touch
                        and self._puck.last_players_to_touch[
                            scoring_team.get_id()]):
                    self.stats.player_scored(self._puck.last_players_to_touch[
                        scoring_team.get_id()],
                                             100,
                                             big_message=True)

                # End game if we won.
                if team.gamedata['score'] >= self.settings['Score to Win']:
                    self.end_game()

        ba.playsound(self._foghorn_sound)
        ba.playsound(self._cheer_sound)

        self._puck.scored = True

        # Kill the puck (it'll respawn itself shortly).
        ba.timer(1.0, self._kill_puck)

        light = ba.newnode('light',
                           attrs={
                               'position': ba.get_collision_info('position'),
                               'height_attenuated': False,
                               'color': (1, 0, 0)
                           })
        ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
        ba.timer(1.0, light.delete)

        ba.cameraflash(duration=10.0)
        self._update_scoreboard()
예제 #2
0
    def _handle_score(self) -> None:
        """A point has been scored."""

        # Our flag might stick around for a second or two
        # make sure it doesn't score again.
        assert self._flag is not None
        if self._flag.scored:
            return
        region = ba.get_collision_info('source_node')
        i = None
        for i in range(len(self._score_regions)):
            if region == self._score_regions[i].node:
                break
        for team in self.teams:
            if team.get_id() == i:
                team.gamedata['score'] += 7

                # Tell all players to celebrate.
                for player in team.players:
                    if player.actor:
                        player.actor.handlemessage(ba.CelebrateMessage(2.0))

                # If someone on this team was last to touch it,
                # give them points.
                assert self._flag is not None
                if (self._flag.last_holding_player
                        and team == self._flag.last_holding_player.team):
                    self.stats.player_scored(self._flag.last_holding_player,
                                             50,
                                             big_message=True)
                # end game if we won
                if team.gamedata['score'] >= self.settings['Score to Win']:
                    self.end_game()
        ba.playsound(self._score_sound)
        ba.playsound(self._cheer_sound)
        assert self._flag
        self._flag.scored = True

        # Kill the flag (it'll respawn shortly).
        ba.timer(1.0, self._kill_flag)
        light = ba.newnode('light',
                           attrs={
                               'position': ba.get_collision_info('position'),
                               'height_attenuated': False,
                               'color': (1, 0, 0)
                           })
        ba.animate(light, 'intensity', {0.0: 0, 0.5: 1, 1.0: 0}, loop=True)
        ba.timer(1.0, light.delete)
        ba.cameraflash(duration=10.0)
        self._update_scoreboard()
예제 #3
0
    def _handle_flag_player_collide(self) -> None:
        flagnode, playernode = ba.get_collision_info('source_node',
                                                     'opposing_node')
        try:
            player = playernode.getdelegate().getplayer()
            flag = flagnode.getdelegate()
        except Exception:
            return  # Player may have left and his body hit the flag.
        assert isinstance(player, ba.Player)
        assert isinstance(flag, ConquestFlag)
        assert flag.light

        if flag.team is not player.team:
            flag.team = player.team
            flag.light.color = player.team.color
            flag.node.color = player.team.color
            self.stats.player_scored(player, 10, screenmessage=False)
            ba.playsound(self._swipsound)
            self._flash_flag(flag)
            self._update_scores()

            # Respawn any players on this team that were in limbo due to the
            # lack of a flag for their team.
            for otherplayer in self.players:
                if (otherplayer.team is flag.team
                        and otherplayer.actor is not None
                        and not otherplayer.is_alive()
                        and otherplayer.gamedata['respawn_timer'] is None):
                    self.spawn_player(otherplayer)
예제 #4
0
 def _handle_splat(self) -> None:
     node = ba.get_collision_info('opposing_node')
     if (node is not self.owner
             and ba.time() - self._last_sticky_sound_time > 1.0):
         self._last_sticky_sound_time = ba.time()
         assert self.node
         ba.playsound(get_factory().sticky_impact_sound,
                      2.0,
                      position=self.node.position)
예제 #5
0
 def _handle_reset_collide(self) -> None:
     # If we have a chosen one, ignore these.
     if self._get_chosen_one_player() is not None:
         return
     delegate = ba.get_collision_info('opposing_node').getdelegate()
     if isinstance(delegate, PlayerSpaz):
         player = ba.playercast_o(Player, delegate.getplayer())
         if player is not None and player.is_alive():
             self._set_chosen_one_player(player)
예제 #6
0
 def _handle_puck_player_collide(self) -> None:
     try:
         pucknode, playernode = ba.get_collision_info(
             'source_node', 'opposing_node')
         puck = pucknode.getdelegate()
         player = playernode.getdelegate().getplayer()
     except Exception:
         player = puck = None
     if player and puck:
         puck.last_players_to_touch[player.team.get_id()] = player
예제 #7
0
    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.")
예제 #8
0
    def _handle_flag_entered_base(self, team: ba.Team) -> None:
        node = ba.get_collision_info('opposing_node')
        assert isinstance(node, (ba.Node, type(None)))
        flag = CTFFlag.from_node(node)
        if not flag:
            print('Unable to get flag in _handle_flag_entered_base')
            return

        if flag.team is team:
            team.gamedata['home_flag_at_base'] = True

            # If the enemy flag is already here, score!
            if team.gamedata['enemy_flag_at_base']:
                self._score(team)
        else:
            team.gamedata['enemy_flag_at_base'] = True
            if team.gamedata['home_flag_at_base']:
                # Award points to whoever was carrying the enemy flag.
                player = flag.last_player_to_hold
                if player and player.team is team:
                    assert self.stats
                    self.stats.player_scored(player, 50, big_message=True)

                # Update score and reset flags.
                self._score(team)

            # If the home-team flag isn't here, print a message to that effect.
            else:
                # Don't want slo-mo affecting this
                curtime = ba.time(ba.TimeType.BASE)
                if curtime - self._last_home_flag_notice_print_time > 5.0:
                    self._last_home_flag_notice_print_time = curtime
                    bpos = team.gamedata['base_pos']
                    tval = ba.Lstr(resource='ownFlagAtYourBaseWarning')
                    tnode = ba.newnode('text',
                                       attrs={
                                           'text':
                                           tval,
                                           'in_world':
                                           True,
                                           'scale':
                                           0.013,
                                           'color': (1, 1, 0, 1),
                                           'h_align':
                                           'center',
                                           'position':
                                           (bpos[0], bpos[1] + 3.2, bpos[2])
                                       })
                    ba.timer(5.1, tnode.delete)
                    ba.animate(tnode, 'scale', {
                        0.0: 0,
                        0.2: 0.013,
                        4.8: 0.013,
                        5.0: 0
                    })
예제 #9
0
 def _handle_reset_collide(self) -> None:
     # If we have a chosen one, ignore these.
     if self._get_chosen_one_player() is not None:
         return
     try:
         player = (ba.get_collision_info(
             'opposing_node').getdelegate().getplayer())
     except Exception:
         return
     if player is not None and player.is_alive():
         self._set_chosen_one_player(player)
예제 #10
0
 def _handle_puck_player_collide(self) -> None:
     try:
         pucknode, playernode = ba.get_collision_info(
             'source_node', 'opposing_node')
         puck = pucknode.getdelegate()
         player = playernode.getdelegate().getplayer()
     except Exception:
         player = puck = None
     assert isinstance(player, Player)
     assert isinstance(puck, Puck)
     if player and puck:
         puck.last_players_to_touch[player.team.id] = player
예제 #11
0
    def _handle_player_flag_region_collide(self, colliding: bool) -> None:
        playernode = ba.get_collision_info('opposing_node')
        try:
            player = playernode.getdelegate().getplayer()
        except Exception:
            return

        # Different parts of us can collide so a single value isn't enough
        # also don't count it if we're dead (flying heads shouldn't be able to
        # win the game :-)
        if colliding and player.is_alive():
            player.gamedata['at_flag'] += 1
        else:
            player.gamedata['at_flag'] = max(0, player.gamedata['at_flag'] - 1)

        self._update_flag_state()
예제 #12
0
 def _handle_impact(self) -> None:
     node = ba.get_collision_info('opposing_node')
     # if we're an impact bomb and we came from this node, don't explode...
     # alternately if we're hitting another impact-bomb from the same
     # source, don't explode...
     try:
         node_delegate = node.getdelegate()
     except Exception:
         node_delegate = None
     if node:
         if (self.bomb_type == 'impact' and
             (node is self.owner or
              (isinstance(node_delegate, Bomb) and node_delegate.bomb_type
               == 'impact' and node_delegate.owner is self.owner))):
             return
         self.handlemessage(ExplodeMessage())
예제 #13
0
    def _handle_player_flag_region_collide(self, colliding: bool) -> None:
        delegate = ba.get_collision_info('opposing_node').getdelegate()
        if not isinstance(delegate, PlayerSpaz):
            return
        player = ba.playercast_o(Player, delegate.getplayer())
        if not player:
            return

        # Different parts of us can collide so a single value isn't enough
        # also don't count it if we're dead (flying heads shouldn't be able to
        # win the game :-)
        if colliding and player.is_alive():
            player.time_at_flag += 1
        else:
            player.time_at_flag = max(0, player.time_at_flag - 1)

        self._update_flag_state()
예제 #14
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())
예제 #15
0
    def _handle_flag_left_base(self, team: Team) -> None:
        cur_time = ba.time()
        op_node = ba.get_collision_info('opposing_node')
        assert isinstance(op_node, (ba.Node, type(None)))
        flag = CTFFlag.from_node(op_node)
        if not flag:
            return
        if flag.team is team:

            # Check times here to prevent too much flashing.
            if (team.last_flag_leave_time is None
                    or cur_time - team.last_flag_leave_time > 3.0):
                ba.playsound(self._alarmsound, position=team.base_pos)
                self._flash_base(team)
            team.last_flag_leave_time = cur_time
            team.home_flag_at_base = False
        else:
            team.enemy_flag_at_base = False
예제 #16
0
    def _handle_flag_left_base(self, team: ba.Team) -> None:
        cur_time = ba.time()
        op_node = ba.get_collision_info("opposing_node")
        assert isinstance(op_node, (ba.Node, type(None)))
        flag = CTFFlag.from_node(op_node)
        if not flag:
            return

        if flag.team is team:

            # Check times here to prevent too much flashing.
            if ('last_flag_leave_time' not in team.gamedata
                    or cur_time - team.gamedata['last_flag_leave_time'] > 3.0):
                ba.playsound(self._alarmsound,
                             position=team.gamedata['base_pos'])
                self._flash_base(team)
            team.gamedata['last_flag_leave_time'] = cur_time
            team.gamedata['home_flag_at_base'] = False
        else:
            team.gamedata['enemy_flag_at_base'] = False
예제 #17
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)
예제 #18
0
    def handlemessage(self, msg: Any) -> Any:
        if __debug__:
            self._handlemessage_sanity_check()

        if isinstance(msg, ba.DieMessage):
            if self.node:
                self.node.delete()

        elif isinstance(msg, ExplodeHitMessage):
            node = ba.get_collision_info('opposing_node')
            if node:
                assert self.node
                nodepos = self.node.position

                # new
                mag = 2000.0
                if self.blast_type == 'ice':
                    mag *= 0.5
                elif self.blast_type == 'land_mine':
                    mag *= 2.5
                elif self.blast_type == 'tnt':
                    mag *= 2.0

                node.handlemessage(
                    ba.HitMessage(pos=nodepos,
                                  velocity=(0, 0, 0),
                                  magnitude=mag,
                                  hit_type=self.hit_type,
                                  hit_subtype=self.hit_subtype,
                                  radius=self.radius,
                                  source_player=ba.existing(
                                      self.source_player)))
                if self.blast_type == 'ice':
                    ba.playsound(get_factory().freeze_sound,
                                 10,
                                 position=nodepos)
                    node.handlemessage(ba.FreezeMessage())

        else:
            super().handlemessage(msg)
예제 #19
0
    def _handle_score(self) -> None:
        """ a point has been scored """
        # FIXME tidy this up
        # pylint: disable=too-many-branches

        # Our flag might stick around for a second or two;
        # we don't want it to be able to score again.
        assert self._flag is not None
        if self._flag.scored:
            return

        # See which score region it was.
        region = ba.get_collision_info('source_node')
        i = None
        for i in range(len(self.score_regions)):
            if region == self.score_regions[i].node:
                break

        for team in [self.teams[0], self._bot_team]:
            assert team is not None
            if team.get_id() == i:
                team.gamedata['score'] += 7

                # Tell all players (or bots) to celebrate.
                if i == 0:
                    for player in team.players:
                        if player.actor:
                            player.actor.handlemessage(
                                ba.CelebrateMessage(2.0))
                else:
                    self._bots.celebrate(2.0)

        # If the good guys scored, add more enemies.
        if i == 0:
            if self.teams[0].gamedata['score'] == 7:
                assert self._bot_types_7 is not None
                for bottype in self._bot_types_7:
                    self._spawn_bot(bottype)
            elif self.teams[0].gamedata['score'] == 14:
                assert self._bot_types_14 is not None
                for bottype in self._bot_types_14:
                    self._spawn_bot(bottype)

        ba.playsound(self._score_sound)
        if i == 0:
            ba.playsound(self._cheer_sound)
        else:
            ba.playsound(self._boo_sound)

        # Kill the flag (it'll respawn shortly).
        self._flag.scored = True

        ba.timer(0.2, self._kill_flag)

        self.update_scores()
        light = ba.newnode('light',
                           attrs={
                               'position': ba.get_collision_info('position'),
                               'height_attenuated': False,
                               'color': (1, 0, 0)
                           })
        ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
        ba.timer(1.0, light.delete)
        if i == 0:
            ba.cameraflash(duration=10.0)
예제 #20
0
    def _handle_race_point_collide(self) -> None:
        # FIXME: Tidy this up.
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-nested-blocks
        region_node, playernode = ba.get_collision_info(
            'source_node', 'opposing_node')
        try:
            player = playernode.getdelegate().getplayer()
        except Exception:
            player = None
        region = region_node.getdelegate()
        if not player or not region:
            return
        assert isinstance(player, ba.Player)
        assert isinstance(region, RaceRegion)

        last_region = player.gamedata['last_region']
        this_region = region.index

        if last_region != this_region:

            # If a player tries to skip regions, smite them.
            # Allow a one region leeway though (its plausible players can get
            # blown over a region, etc).
            if this_region > last_region + 2:
                if player.is_alive():
                    assert player.actor
                    player.actor.handlemessage(ba.DieMessage())
                    ba.screenmessage(ba.Lstr(
                        translate=('statements', 'Killing ${NAME} for'
                                   ' skipping part of the track!'),
                        subs=[('${NAME}', player.get_name(full=True))]),
                                     color=(1, 0, 0))
            else:
                # If this player is in first, note that this is the
                # front-most race-point.
                if player.gamedata['rank'] == 0:
                    self._front_race_region = this_region

                player.gamedata['last_region'] = this_region
                if last_region >= len(self._regions) - 2 and this_region == 0:
                    team = player.team
                    player.gamedata['lap'] = min(self.settings['Laps'],
                                                 player.gamedata['lap'] + 1)

                    # In teams mode with all-must-finish on, the team lap
                    # value is the min of all team players.
                    # Otherwise its the max.
                    if isinstance(self.session,
                                  ba.DualTeamSession) and self.settings.get(
                                      'Entire Team Must Finish'):
                        team.gamedata['lap'] = min(
                            [p.gamedata['lap'] for p in team.players])
                    else:
                        team.gamedata['lap'] = max(
                            [p.gamedata['lap'] for p in team.players])

                    # A player is finishing.
                    if player.gamedata['lap'] == self.settings['Laps']:

                        # In teams mode, hand out points based on the order
                        # players come in.
                        if isinstance(self.session, ba.DualTeamSession):
                            assert self._team_finish_pts is not None
                            if self._team_finish_pts > 0:
                                self.stats.player_scored(player,
                                                         self._team_finish_pts,
                                                         screenmessage=False)
                            self._team_finish_pts -= 25

                        # Flash where the player is.
                        self._flash_player(player, 1.0)
                        player.gamedata['finished'] = True
                        assert player.actor
                        player.actor.handlemessage(
                            ba.DieMessage(immediate=True))

                        # Makes sure noone behind them passes them in rank
                        # while finishing.
                        player.gamedata['distance'] = 9999.0

                        # If the whole team has finished the race.
                        if team.gamedata['lap'] == self.settings['Laps']:
                            ba.playsound(self._score_sound)
                            player.team.gamedata['finished'] = True
                            assert self._timer is not None
                            cur_time = ba.time(
                                timeformat=ba.TimeFormat.MILLISECONDS)
                            start_time = self._timer.getstarttime(
                                timeformat=ba.TimeFormat.MILLISECONDS)
                            self._last_team_time = (
                                player.team.gamedata['time']) = (cur_time -
                                                                 start_time)
                            self._check_end_game()

                        # Team has yet to finish.
                        else:
                            ba.playsound(self._swipsound)

                    # They've just finished a lap but not the race.
                    else:
                        ba.playsound(self._swipsound)
                        self._flash_player(player, 0.3)

                        # Print their lap number over their head.
                        try:
                            assert isinstance(player.actor, PlayerSpaz)
                            mathnode = ba.newnode('math',
                                                  owner=player.actor.node,
                                                  attrs={
                                                      'input1': (0, 1.9, 0),
                                                      'operation': 'add'
                                                  })
                            player.actor.node.connectattr(
                                'torso_position', mathnode, 'input2')
                            tstr = ba.Lstr(resource='lapNumberText',
                                           subs=[('${CURRENT}',
                                                  str(player.gamedata['lap'] +
                                                      1)),
                                                 ('${TOTAL}',
                                                  str(self.settings['Laps']))])
                            txtnode = ba.newnode('text',
                                                 owner=mathnode,
                                                 attrs={
                                                     'text': tstr,
                                                     'in_world': True,
                                                     'color': (1, 1, 0, 1),
                                                     'scale': 0.015,
                                                     'h_align': 'center'
                                                 })
                            mathnode.connectattr('output', txtnode, 'position')
                            ba.animate(txtnode, 'scale', {
                                0.0: 0,
                                0.2: 0.019,
                                2.0: 0.019,
                                2.2: 0
                            })
                            ba.timer(2.3, mathnode.delete)
                        except Exception as exc:
                            print('Exception printing lap:', exc)
예제 #21
0
    def _handle_base_collide(self, team: ba.Team) -> None:

        # Attempt to pull a living ba.Player from what we hit.
        cnode = ba.get_collision_info('opposing_node')
        assert isinstance(cnode, ba.Node)
        actor = cnode.getdelegate()
        if not isinstance(actor, playerspaz.PlayerSpaz):
            return
        player = actor.getplayer()
        if not player or not player.is_alive():
            return

        # If its another team's player, they scored.
        player_team = player.team
        if player_team is not team:

            # Prevent multiple simultaneous scores.
            if ba.time() != self._last_score_time:
                self._last_score_time = ba.time()
                self.stats.player_scored(player, 50, big_message=True)
                ba.playsound(self._score_sound)
                self._flash_base(team)

                # Move all players on the scoring team back to their start
                # and add flashes of light so its noticeable.
                for player in player_team.players:
                    if player.is_alive():
                        if player.node:
                            pos = player.node.position
                            light = ba.newnode('light',
                                               attrs={
                                                   'position': pos,
                                                   'color': player_team.color,
                                                   'height_attenuated': False,
                                                   'radius': 0.4
                                               })
                            ba.timer(0.5, light.delete)
                            ba.animate(light, 'intensity', {
                                0: 0,
                                0.1: 1.0,
                                0.5: 0
                            })

                        new_pos = (self.map.get_start_position(
                            player_team.get_id()))
                        light = ba.newnode('light',
                                           attrs={
                                               'position': new_pos,
                                               'color': player_team.color,
                                               'radius': 0.4,
                                               'height_attenuated': False
                                           })
                        ba.timer(0.5, light.delete)
                        ba.animate(light, 'intensity', {
                            0: 0,
                            0.1: 1.0,
                            0.5: 0
                        })
                        if player.actor:
                            player.actor.handlemessage(
                                ba.StandMessage(new_pos,
                                                random.uniform(0, 360)))

                # Have teammates celebrate.
                for player in player_team.players:
                    if player.actor:
                        player.actor.handlemessage(ba.CelebrateMessage(2.0))

                player_team.gamedata['score'] += 1
                self._update_scoreboard()
                if (player_team.gamedata['score'] >=
                        self.settings_raw['Score to Win']):
                    self.end_game()