예제 #1
0
    def _touch_return_update(self, team: ba.Team) -> None:

        # Count down only while its away from base and not being held.
        if (team.gamedata['home_flag_at_base']
                or team.gamedata['flag'].held_count > 0):
            team.gamedata['touch_return_timer_ticking'] = None
            return  # No need to return when its at home.
        if team.gamedata['touch_return_timer_ticking'] is None:
            team.gamedata['touch_return_timer_ticking'] = ba.NodeActor(
                ba.newnode('sound',
                           attrs={
                               'sound': self._ticking_sound,
                               'positional': False,
                               'loop': True
                           }))
        flag = team.gamedata['flag']
        flag.touch_return_time -= 0.1
        if flag.counter:
            flag.counter.text = '%.1f' % flag.touch_return_time
            flag.counter.color = (1, 1, 0, 1)
            flag.counter.scale = 0.02

        if flag.touch_return_time <= 0.0:
            self._award_players_touching_own_flag(team)
            flag.handlemessage(ba.DieMessage())
예제 #2
0
 def _add_team(self, team: ba.Team) -> None:
     if team.get_id() in self._entries:
         raise Exception('Duplicate team add')
     self._entries[team.get_id()] = _Entry(self,
                                           team,
                                           do_cover=self._do_cover,
                                           scale=self._scale,
                                           label=self._label,
                                           flash_length=self._flash_length)
     self._update_teams()
예제 #3
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
                    })
예제 #4
0
    def set_team_score(self, team: ba.Team, score: int) -> None:
        """Set the score for a given ba.Team.

        This can be a number or None.
        (see the none_is_winner arg in the constructor)
        """
        self._scores[team.get_id()] = (weakref.ref(team), score)
예제 #5
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.")
예제 #6
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
예제 #7
0
 def set_team_value(self,
                    team: ba.Team,
                    score: int,
                    max_score: int = None,
                    countdown: bool = False,
                    flash: bool = True,
                    show_value: bool = True) -> None:
     """Update the score-board display for the given ba.Team."""
     if not team.get_id() in self._entries:
         self._add_team(team)
         # create a proxy in the team which will kill
         # our entry when it dies (for convenience)
         if '_scoreboard_entry' in team.gamedata:
             raise Exception("existing _EntryProxy found")
         team.gamedata['_scoreboard_entry'] = _EntryProxy(self, team)
     # now set the entry..
     self._entries[team.get_id()].set_value(score=score,
                                            max_score=max_score,
                                            countdown=countdown,
                                            flash=flash,
                                            show_value=show_value)
예제 #8
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['score'] = 0
     if self.has_begun():
         self._update_scoreboard()
예제 #9
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['score'] = 0
     self._update_scoreboard()
예제 #10
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['time_remaining'] = self.settings['Hold Time']
     self._update_scoreboard()
예제 #11
0
 def __init__(self, scoreboard: Scoreboard, team: ba.Team):
     self._scoreboard = weakref.ref(scoreboard)
     # have to store ID here instead of a weak-ref since the team will be
     # dead when we die and need to remove it
     self._team_id = team.get_id()
예제 #12
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['survival_seconds'] = None
     team.gamedata['spawn_order'] = []
예제 #13
0
 def _spawn_flag_for_team(self, team: ba.Team) -> None:
     flag = team.gamedata['flag'] = CTFFlag(team)
     team.gamedata['flag_return_touches'] = 0
     self._flash_base(team, length=1.0)
     assert flag.node
     ba.playsound(self._swipsound, position=flag.node.position)
예제 #14
0
    def on_team_join(self, team: ba.Team) -> None:
        team.gamedata['score'] = 0
        team.gamedata['flag_return_touches'] = 0
        team.gamedata['home_flag_at_base'] = True
        team.gamedata['touch_return_timer'] = None
        team.gamedata['enemy_flag_at_base'] = False
        team.gamedata['base_pos'] = (self.map.get_flag_position(team.get_id()))

        self.project_flag_stand(team.gamedata['base_pos'])

        ba.newnode('light',
                   attrs={
                       'position': team.gamedata['base_pos'],
                       'intensity': 0.6,
                       'height_attenuated': False,
                       'volume_intensity_scale': 0.1,
                       'radius': 0.1,
                       'color': team.color
                   })

        base_region_mat = team.gamedata['base_region_material'] = ba.Material()
        pos = team.gamedata['base_pos']
        team.gamedata['base_region'] = ba.newnode(
            'region',
            attrs={
                'position': (pos[0], pos[1] + 0.75, pos[2]),
                'scale': (0.5, 0.5, 0.5),
                'type': 'sphere',
                'materials': [base_region_mat, self._all_bases_material]
            })

        # create some materials for this team
        spaz_mat_no_flag_physical = team.gamedata[
            'spaz_material_no_flag_physical'] = ba.Material()
        spaz_mat_no_flag_collide = team.gamedata[
            'spaz_material_no_flag_collide'] = ba.Material()
        flagmat = team.gamedata['flagmaterial'] = ba.Material()

        # Some parts of our spazzes don't collide physically with our
        # flags but generate callbacks.
        spaz_mat_no_flag_physical.add_actions(
            conditions=('they_have_material', flagmat),
            actions=(('modify_part_collision', 'physical',
                      False), ('call', 'at_connect',
                               lambda: self._handle_hit_own_flag(team, 1)),
                     ('call', 'at_disconnect',
                      lambda: self._handle_hit_own_flag(team, 0))))

        # Other parts of our spazzes don't collide with our flags at all.
        spaz_mat_no_flag_collide.add_actions(conditions=('they_have_material',
                                                         flagmat),
                                             actions=('modify_part_collision',
                                                      'collide', False))

        # We wanna know when *any* flag enters/leaves our base.
        base_region_mat.add_actions(
            conditions=('they_have_material',
                        stdflag.get_factory().flagmaterial),
            actions=(('modify_part_collision', 'collide',
                      True), ('modify_part_collision', 'physical', False),
                     ('call', 'at_connect',
                      lambda: self._handle_flag_entered_base(team)),
                     ('call', 'at_disconnect',
                      lambda: self._handle_flag_left_base(team))))

        self._spawn_flag_for_team(team)
        self._update_scoreboard()
예제 #15
0
 def on_team_join(self, team: ba.Team) -> None:
     if self.has_begun():
         self._update_scores()
     team.gamedata['flags_held'] = 0
예제 #16
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['time'] = None
     team.gamedata['lap'] = 0
     team.gamedata['finished'] = False
     self._update_scoreboard()
예제 #17
0
 def on_team_join(self, team: ba.Team) -> None:
     team.gamedata['time_remaining'] = self.settings["Chosen One Time"]
     self._update_scoreboard()