bascenev1lib.game.assault

Defines assault minigame.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Defines assault minigame."""
  4
  5# ba_meta require api 8
  6# (see https://ballistica.net/wiki/meta-tag-system)
  7
  8from __future__ import annotations
  9
 10import random
 11from typing import TYPE_CHECKING
 12
 13from bascenev1lib.actor.playerspaz import PlayerSpaz
 14from bascenev1lib.actor.flag import Flag
 15from bascenev1lib.actor.scoreboard import Scoreboard
 16from bascenev1lib.gameutils import SharedObjects
 17import bascenev1 as bs
 18
 19if TYPE_CHECKING:
 20    from typing import Any, Sequence
 21
 22
 23class Player(bs.Player['Team']):
 24    """Our player type for this game."""
 25
 26
 27class Team(bs.Team[Player]):
 28    """Our team type for this game."""
 29
 30    def __init__(self, base_pos: Sequence[float], flag: Flag) -> None:
 31        self.base_pos = base_pos
 32        self.flag = flag
 33        self.score = 0
 34
 35
 36# ba_meta export bascenev1.GameActivity
 37class AssaultGame(bs.TeamGameActivity[Player, Team]):
 38    """Game where you score by touching the other team's flag."""
 39
 40    name = 'Assault'
 41    description = 'Reach the enemy flag to score.'
 42    available_settings = [
 43        bs.IntSetting(
 44            'Score to Win',
 45            min_value=1,
 46            default=3,
 47        ),
 48        bs.IntChoiceSetting(
 49            'Time Limit',
 50            choices=[
 51                ('None', 0),
 52                ('1 Minute', 60),
 53                ('2 Minutes', 120),
 54                ('5 Minutes', 300),
 55                ('10 Minutes', 600),
 56                ('20 Minutes', 1200),
 57            ],
 58            default=0,
 59        ),
 60        bs.FloatChoiceSetting(
 61            'Respawn Times',
 62            choices=[
 63                ('Shorter', 0.25),
 64                ('Short', 0.5),
 65                ('Normal', 1.0),
 66                ('Long', 2.0),
 67                ('Longer', 4.0),
 68            ],
 69            default=1.0,
 70        ),
 71        bs.BoolSetting('Epic Mode', default=False),
 72    ]
 73
 74    @classmethod
 75    def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
 76        return issubclass(sessiontype, bs.DualTeamSession)
 77
 78    @classmethod
 79    def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
 80        assert bs.app.classic is not None
 81        return bs.app.classic.getmaps('team_flag')
 82
 83    def __init__(self, settings: dict):
 84        super().__init__(settings)
 85        self._scoreboard = Scoreboard()
 86        self._last_score_time = 0.0
 87        self._score_sound = bs.getsound('score')
 88        self._base_region_materials: dict[int, bs.Material] = {}
 89        self._epic_mode = bool(settings['Epic Mode'])
 90        self._score_to_win = int(settings['Score to Win'])
 91        self._time_limit = float(settings['Time Limit'])
 92
 93        # Base class overrides
 94        self.slow_motion = self._epic_mode
 95        self.default_music = (
 96            bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH
 97        )
 98
 99    def get_instance_description(self) -> str | Sequence:
100        if self._score_to_win == 1:
101            return 'Touch the enemy flag.'
102        return 'Touch the enemy flag ${ARG1} times.', self._score_to_win
103
104    def get_instance_description_short(self) -> str | Sequence:
105        if self._score_to_win == 1:
106            return 'touch 1 flag'
107        return 'touch ${ARG1} flags', self._score_to_win
108
109    def create_team(self, sessionteam: bs.SessionTeam) -> Team:
110        shared = SharedObjects.get()
111        base_pos = self.map.get_flag_position(sessionteam.id)
112        bs.newnode(
113            'light',
114            attrs={
115                'position': base_pos,
116                'intensity': 0.6,
117                'height_attenuated': False,
118                'volume_intensity_scale': 0.1,
119                'radius': 0.1,
120                'color': sessionteam.color,
121            },
122        )
123        Flag.project_stand(base_pos)
124        flag = Flag(touchable=False, position=base_pos, color=sessionteam.color)
125        team = Team(base_pos=base_pos, flag=flag)
126
127        mat = self._base_region_materials[sessionteam.id] = bs.Material()
128        mat.add_actions(
129            conditions=('they_have_material', shared.player_material),
130            actions=(
131                ('modify_part_collision', 'collide', True),
132                ('modify_part_collision', 'physical', False),
133                (
134                    'call',
135                    'at_connect',
136                    bs.Call(self._handle_base_collide, team),
137                ),
138            ),
139        )
140
141        bs.newnode(
142            'region',
143            owner=flag.node,
144            attrs={
145                'position': (base_pos[0], base_pos[1] + 0.75, base_pos[2]),
146                'scale': (0.5, 0.5, 0.5),
147                'type': 'sphere',
148                'materials': [self._base_region_materials[sessionteam.id]],
149            },
150        )
151
152        return team
153
154    def on_team_join(self, team: Team) -> None:
155        # Can't do this in create_team because the team's color/etc. have
156        # not been wired up yet at that point.
157        self._update_scoreboard()
158
159    def on_begin(self) -> None:
160        super().on_begin()
161        self.setup_standard_time_limit(self._time_limit)
162        self.setup_standard_powerup_drops()
163
164    def handlemessage(self, msg: Any) -> Any:
165        if isinstance(msg, bs.PlayerDiedMessage):
166            super().handlemessage(msg)  # Augment standard.
167            self.respawn_player(msg.getplayer(Player))
168        else:
169            super().handlemessage(msg)
170
171    def _flash_base(self, team: Team, length: float = 2.0) -> None:
172        light = bs.newnode(
173            'light',
174            attrs={
175                'position': team.base_pos,
176                'height_attenuated': False,
177                'radius': 0.3,
178                'color': team.color,
179            },
180        )
181        bs.animate(light, 'intensity', {0: 0, 0.25: 2.0, 0.5: 0}, loop=True)
182        bs.timer(length, light.delete)
183
184    def _handle_base_collide(self, team: Team) -> None:
185        try:
186            spaz = bs.getcollision().opposingnode.getdelegate(PlayerSpaz, True)
187        except bs.NotFoundError:
188            return
189
190        if not spaz.is_alive():
191            return
192
193        try:
194            player = spaz.getplayer(Player, True)
195        except bs.NotFoundError:
196            return
197
198        # If its another team's player, they scored.
199        player_team = player.team
200        if player_team is not team:
201            # Prevent multiple simultaneous scores.
202            if bs.time() != self._last_score_time:
203                self._last_score_time = bs.time()
204                self.stats.player_scored(player, 50, big_message=True)
205                self._score_sound.play()
206                self._flash_base(team)
207
208                # Move all players on the scoring team back to their start
209                # and add flashes of light so its noticeable.
210                for player in player_team.players:
211                    if player.is_alive():
212                        pos = player.node.position
213                        light = bs.newnode(
214                            'light',
215                            attrs={
216                                'position': pos,
217                                'color': player_team.color,
218                                'height_attenuated': False,
219                                'radius': 0.4,
220                            },
221                        )
222                        bs.timer(0.5, light.delete)
223                        bs.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.5: 0})
224
225                        new_pos = self.map.get_start_position(player_team.id)
226                        light = bs.newnode(
227                            'light',
228                            attrs={
229                                'position': new_pos,
230                                'color': player_team.color,
231                                'radius': 0.4,
232                                'height_attenuated': False,
233                            },
234                        )
235                        bs.timer(0.5, light.delete)
236                        bs.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.5: 0})
237                        if player.actor:
238                            player.actor.handlemessage(
239                                bs.StandMessage(new_pos, random.uniform(0, 360))
240                            )
241
242                # Have teammates celebrate.
243                for player in player_team.players:
244                    if player.actor:
245                        player.actor.handlemessage(bs.CelebrateMessage(2.0))
246
247                player_team.score += 1
248                self._update_scoreboard()
249                if player_team.score >= self._score_to_win:
250                    self.end_game()
251
252    def end_game(self) -> None:
253        results = bs.GameResults()
254        for team in self.teams:
255            results.set_team_score(team, team.score)
256        self.end(results=results)
257
258    def _update_scoreboard(self) -> None:
259        for team in self.teams:
260            self._scoreboard.set_team_value(
261                team, team.score, self._score_to_win
262            )
class Player(bascenev1._player.Player[ForwardRef('Team')]):
24class Player(bs.Player['Team']):
25    """Our player type for this game."""

Our player type for this game.

Inherited Members
bascenev1._player.Player
character
actor
color
highlight
on_expire
team
customdata
sessionplayer
node
position
exists
getname
is_alive
get_icon
assigninput
resetinput
class Team(bascenev1._team.Team[bascenev1lib.game.assault.Player]):
28class Team(bs.Team[Player]):
29    """Our team type for this game."""
30
31    def __init__(self, base_pos: Sequence[float], flag: Flag) -> None:
32        self.base_pos = base_pos
33        self.flag = flag
34        self.score = 0

Our team type for this game.

Team(base_pos: Sequence[float], flag: bascenev1lib.actor.flag.Flag)
31    def __init__(self, base_pos: Sequence[float], flag: Flag) -> None:
32        self.base_pos = base_pos
33        self.flag = flag
34        self.score = 0
base_pos
flag
score
Inherited Members
bascenev1._team.Team
players
id
name
color
manual_init
customdata
on_expire
sessionteam
class AssaultGame(bascenev1._teamgame.TeamGameActivity[bascenev1lib.game.assault.Player, bascenev1lib.game.assault.Team]):
 38class AssaultGame(bs.TeamGameActivity[Player, Team]):
 39    """Game where you score by touching the other team's flag."""
 40
 41    name = 'Assault'
 42    description = 'Reach the enemy flag to score.'
 43    available_settings = [
 44        bs.IntSetting(
 45            'Score to Win',
 46            min_value=1,
 47            default=3,
 48        ),
 49        bs.IntChoiceSetting(
 50            'Time Limit',
 51            choices=[
 52                ('None', 0),
 53                ('1 Minute', 60),
 54                ('2 Minutes', 120),
 55                ('5 Minutes', 300),
 56                ('10 Minutes', 600),
 57                ('20 Minutes', 1200),
 58            ],
 59            default=0,
 60        ),
 61        bs.FloatChoiceSetting(
 62            'Respawn Times',
 63            choices=[
 64                ('Shorter', 0.25),
 65                ('Short', 0.5),
 66                ('Normal', 1.0),
 67                ('Long', 2.0),
 68                ('Longer', 4.0),
 69            ],
 70            default=1.0,
 71        ),
 72        bs.BoolSetting('Epic Mode', default=False),
 73    ]
 74
 75    @classmethod
 76    def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
 77        return issubclass(sessiontype, bs.DualTeamSession)
 78
 79    @classmethod
 80    def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
 81        assert bs.app.classic is not None
 82        return bs.app.classic.getmaps('team_flag')
 83
 84    def __init__(self, settings: dict):
 85        super().__init__(settings)
 86        self._scoreboard = Scoreboard()
 87        self._last_score_time = 0.0
 88        self._score_sound = bs.getsound('score')
 89        self._base_region_materials: dict[int, bs.Material] = {}
 90        self._epic_mode = bool(settings['Epic Mode'])
 91        self._score_to_win = int(settings['Score to Win'])
 92        self._time_limit = float(settings['Time Limit'])
 93
 94        # Base class overrides
 95        self.slow_motion = self._epic_mode
 96        self.default_music = (
 97            bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH
 98        )
 99
100    def get_instance_description(self) -> str | Sequence:
101        if self._score_to_win == 1:
102            return 'Touch the enemy flag.'
103        return 'Touch the enemy flag ${ARG1} times.', self._score_to_win
104
105    def get_instance_description_short(self) -> str | Sequence:
106        if self._score_to_win == 1:
107            return 'touch 1 flag'
108        return 'touch ${ARG1} flags', self._score_to_win
109
110    def create_team(self, sessionteam: bs.SessionTeam) -> Team:
111        shared = SharedObjects.get()
112        base_pos = self.map.get_flag_position(sessionteam.id)
113        bs.newnode(
114            'light',
115            attrs={
116                'position': base_pos,
117                'intensity': 0.6,
118                'height_attenuated': False,
119                'volume_intensity_scale': 0.1,
120                'radius': 0.1,
121                'color': sessionteam.color,
122            },
123        )
124        Flag.project_stand(base_pos)
125        flag = Flag(touchable=False, position=base_pos, color=sessionteam.color)
126        team = Team(base_pos=base_pos, flag=flag)
127
128        mat = self._base_region_materials[sessionteam.id] = bs.Material()
129        mat.add_actions(
130            conditions=('they_have_material', shared.player_material),
131            actions=(
132                ('modify_part_collision', 'collide', True),
133                ('modify_part_collision', 'physical', False),
134                (
135                    'call',
136                    'at_connect',
137                    bs.Call(self._handle_base_collide, team),
138                ),
139            ),
140        )
141
142        bs.newnode(
143            'region',
144            owner=flag.node,
145            attrs={
146                'position': (base_pos[0], base_pos[1] + 0.75, base_pos[2]),
147                'scale': (0.5, 0.5, 0.5),
148                'type': 'sphere',
149                'materials': [self._base_region_materials[sessionteam.id]],
150            },
151        )
152
153        return team
154
155    def on_team_join(self, team: Team) -> None:
156        # Can't do this in create_team because the team's color/etc. have
157        # not been wired up yet at that point.
158        self._update_scoreboard()
159
160    def on_begin(self) -> None:
161        super().on_begin()
162        self.setup_standard_time_limit(self._time_limit)
163        self.setup_standard_powerup_drops()
164
165    def handlemessage(self, msg: Any) -> Any:
166        if isinstance(msg, bs.PlayerDiedMessage):
167            super().handlemessage(msg)  # Augment standard.
168            self.respawn_player(msg.getplayer(Player))
169        else:
170            super().handlemessage(msg)
171
172    def _flash_base(self, team: Team, length: float = 2.0) -> None:
173        light = bs.newnode(
174            'light',
175            attrs={
176                'position': team.base_pos,
177                'height_attenuated': False,
178                'radius': 0.3,
179                'color': team.color,
180            },
181        )
182        bs.animate(light, 'intensity', {0: 0, 0.25: 2.0, 0.5: 0}, loop=True)
183        bs.timer(length, light.delete)
184
185    def _handle_base_collide(self, team: Team) -> None:
186        try:
187            spaz = bs.getcollision().opposingnode.getdelegate(PlayerSpaz, True)
188        except bs.NotFoundError:
189            return
190
191        if not spaz.is_alive():
192            return
193
194        try:
195            player = spaz.getplayer(Player, True)
196        except bs.NotFoundError:
197            return
198
199        # If its another team's player, they scored.
200        player_team = player.team
201        if player_team is not team:
202            # Prevent multiple simultaneous scores.
203            if bs.time() != self._last_score_time:
204                self._last_score_time = bs.time()
205                self.stats.player_scored(player, 50, big_message=True)
206                self._score_sound.play()
207                self._flash_base(team)
208
209                # Move all players on the scoring team back to their start
210                # and add flashes of light so its noticeable.
211                for player in player_team.players:
212                    if player.is_alive():
213                        pos = player.node.position
214                        light = bs.newnode(
215                            'light',
216                            attrs={
217                                'position': pos,
218                                'color': player_team.color,
219                                'height_attenuated': False,
220                                'radius': 0.4,
221                            },
222                        )
223                        bs.timer(0.5, light.delete)
224                        bs.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.5: 0})
225
226                        new_pos = self.map.get_start_position(player_team.id)
227                        light = bs.newnode(
228                            'light',
229                            attrs={
230                                'position': new_pos,
231                                'color': player_team.color,
232                                'radius': 0.4,
233                                'height_attenuated': False,
234                            },
235                        )
236                        bs.timer(0.5, light.delete)
237                        bs.animate(light, 'intensity', {0: 0, 0.1: 1.0, 0.5: 0})
238                        if player.actor:
239                            player.actor.handlemessage(
240                                bs.StandMessage(new_pos, random.uniform(0, 360))
241                            )
242
243                # Have teammates celebrate.
244                for player in player_team.players:
245                    if player.actor:
246                        player.actor.handlemessage(bs.CelebrateMessage(2.0))
247
248                player_team.score += 1
249                self._update_scoreboard()
250                if player_team.score >= self._score_to_win:
251                    self.end_game()
252
253    def end_game(self) -> None:
254        results = bs.GameResults()
255        for team in self.teams:
256            results.set_team_score(team, team.score)
257        self.end(results=results)
258
259    def _update_scoreboard(self) -> None:
260        for team in self.teams:
261            self._scoreboard.set_team_value(
262                team, team.score, self._score_to_win
263            )

Game where you score by touching the other team's flag.

AssaultGame(settings: dict)
84    def __init__(self, settings: dict):
85        super().__init__(settings)
86        self._scoreboard = Scoreboard()
87        self._last_score_time = 0.0
88        self._score_sound = bs.getsound('score')
89        self._base_region_materials: dict[int, bs.Material] = {}
90        self._epic_mode = bool(settings['Epic Mode'])
91        self._score_to_win = int(settings['Score to Win'])
92        self._time_limit = float(settings['Time Limit'])
93
94        # Base class overrides
95        self.slow_motion = self._epic_mode
96        self.default_music = (
97            bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH
98        )

Instantiate the Activity.

name = 'Assault'
description = 'Reach the enemy flag to score.'
available_settings = [IntSetting(name='Score to Win', default=3, min_value=1, max_value=9999, increment=1), IntChoiceSetting(name='Time Limit', default=0, choices=[('None', 0), ('1 Minute', 60), ('2 Minutes', 120), ('5 Minutes', 300), ('10 Minutes', 600), ('20 Minutes', 1200)]), FloatChoiceSetting(name='Respawn Times', default=1.0, choices=[('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), ('Long', 2.0), ('Longer', 4.0)]), BoolSetting(name='Epic Mode', default=False)]
@classmethod
def supports_session_type(cls, sessiontype: type[bascenev1._session.Session]) -> bool:
75    @classmethod
76    def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
77        return issubclass(sessiontype, bs.DualTeamSession)

Class method override; returns True for ba.DualTeamSessions and ba.FreeForAllSessions; False otherwise.

@classmethod
def get_supported_maps(cls, sessiontype: type[bascenev1._session.Session]) -> list[str]:
79    @classmethod
80    def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
81        assert bs.app.classic is not None
82        return bs.app.classic.getmaps('team_flag')

Called by the default bascenev1.GameActivity.create_settings_ui() implementation; should return a list of map names valid for this game-type for the given bascenev1.Session type.

slow_motion = False

If True, runs in slow motion and turns down sound pitch.

default_music = None
def get_instance_description(self) -> Union[str, Sequence]:
100    def get_instance_description(self) -> str | Sequence:
101        if self._score_to_win == 1:
102            return 'Touch the enemy flag.'
103        return 'Touch the enemy flag ${ARG1} times.', self._score_to_win

Return a description for this game instance, in English.

This is shown in the center of the screen below the game name at the start of a game. It should start with a capital letter and end with a period, and can be a bit more verbose than the version returned by get_instance_description_short().

Note that translation is applied by looking up the specific returned value as a key, so the number of returned variations should be limited; ideally just one or two. To include arbitrary values in the description, you can return a sequence of values in the following form instead of just a string:

This will give us something like 'Score 3 goals.' in English

and can properly translate to 'Anota 3 goles.' in Spanish.

If we just returned the string 'Score 3 Goals' here, there would

have to be a translation entry for each specific number. ew.

return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]

This way the first string can be consistently translated, with any arg values then substituted into the result. ${ARG1} will be replaced with the first value, ${ARG2} with the second, etc.

def get_instance_description_short(self) -> Union[str, Sequence]:
105    def get_instance_description_short(self) -> str | Sequence:
106        if self._score_to_win == 1:
107            return 'touch 1 flag'
108        return 'touch ${ARG1} flags', self._score_to_win

Return a short description for this game instance in English.

This description is used above the game scoreboard in the corner of the screen, so it should be as concise as possible. It should be lowercase and should not contain periods or other punctuation.

Note that translation is applied by looking up the specific returned value as a key, so the number of returned variations should be limited; ideally just one or two. To include arbitrary values in the description, you can return a sequence of values in the following form instead of just a string:

This will give us something like 'score 3 goals' in English

and can properly translate to 'anota 3 goles' in Spanish.

If we just returned the string 'score 3 goals' here, there would

have to be a translation entry for each specific number. ew.

return ['score ${ARG1} goals', self.settings_raw['Score to Win']]

This way the first string can be consistently translated, with any arg values then substituted into the result. ${ARG1} will be replaced with the first value, ${ARG2} with the second, etc.

def create_team( self, sessionteam: bascenev1._team.SessionTeam) -> Team:
110    def create_team(self, sessionteam: bs.SessionTeam) -> Team:
111        shared = SharedObjects.get()
112        base_pos = self.map.get_flag_position(sessionteam.id)
113        bs.newnode(
114            'light',
115            attrs={
116                'position': base_pos,
117                'intensity': 0.6,
118                'height_attenuated': False,
119                'volume_intensity_scale': 0.1,
120                'radius': 0.1,
121                'color': sessionteam.color,
122            },
123        )
124        Flag.project_stand(base_pos)
125        flag = Flag(touchable=False, position=base_pos, color=sessionteam.color)
126        team = Team(base_pos=base_pos, flag=flag)
127
128        mat = self._base_region_materials[sessionteam.id] = bs.Material()
129        mat.add_actions(
130            conditions=('they_have_material', shared.player_material),
131            actions=(
132                ('modify_part_collision', 'collide', True),
133                ('modify_part_collision', 'physical', False),
134                (
135                    'call',
136                    'at_connect',
137                    bs.Call(self._handle_base_collide, team),
138                ),
139            ),
140        )
141
142        bs.newnode(
143            'region',
144            owner=flag.node,
145            attrs={
146                'position': (base_pos[0], base_pos[1] + 0.75, base_pos[2]),
147                'scale': (0.5, 0.5, 0.5),
148                'type': 'sphere',
149                'materials': [self._base_region_materials[sessionteam.id]],
150            },
151        )
152
153        return team

Create the Team instance for this Activity.

Subclasses can override this if the activity's team class requires a custom constructor; otherwise it will be called with no args. Note that the team object should not be used at this point as it is not yet fully wired up; wait for on_team_join() for that.

def on_team_join(self, team: Team) -> None:
155    def on_team_join(self, team: Team) -> None:
156        # Can't do this in create_team because the team's color/etc. have
157        # not been wired up yet at that point.
158        self._update_scoreboard()

Called when a new bascenev1.Team joins the Activity.

(including the initial set of Teams)

def on_begin(self) -> None:
160    def on_begin(self) -> None:
161        super().on_begin()
162        self.setup_standard_time_limit(self._time_limit)
163        self.setup_standard_powerup_drops()

Called once the previous Activity has finished transitioning out.

At this point the activity's initial players and teams are filled in and it should begin its actual game logic.

def handlemessage(self, msg: Any) -> Any:
165    def handlemessage(self, msg: Any) -> Any:
166        if isinstance(msg, bs.PlayerDiedMessage):
167            super().handlemessage(msg)  # Augment standard.
168            self.respawn_player(msg.getplayer(Player))
169        else:
170            super().handlemessage(msg)

General message handling; can be passed any message object.

def end_game(self) -> None:
253    def end_game(self) -> None:
254        results = bs.GameResults()
255        for team in self.teams:
256            results.set_team_score(team, team.score)
257        self.end(results=results)

Tell the game to wrap up and call bascenev1.Activity.end().

This method should be overridden by subclasses. A game should always be prepared to end and deliver results, even if there is no 'winner' yet; this way things like the standard time-limit (bascenev1.GameActivity.setup_standard_time_limit()) will work with the game.

Inherited Members
bascenev1._teamgame.TeamGameActivity
on_transition_in
spawn_player_spaz
end
bascenev1._gameactivity.GameActivity
tips
scoreconfig
allow_pausing
allow_kick_idle_players
show_kill_points
create_settings_ui
getscoreconfig
getname
get_display_string
get_team_display_string
get_description
get_description_display_string
get_available_settings
get_settings_display_string
initialplayerinfos
map
get_instance_display_string
get_instance_scoreboard_display_string
on_continue
is_waiting_for_continue
continue_or_end_game
on_player_join
respawn_player
spawn_player_if_exists
spawn_player
setup_standard_powerup_drops
setup_standard_time_limit
show_zoom_message
bascenev1._activity.Activity
settings_raw
teams
players
announce_player_deaths
is_joining_activity
use_fixed_vr_overlay
inherits_slow_motion
inherits_music
inherits_vr_camera_offset
inherits_vr_overlay_center
inherits_tint
allow_mid_activity_joins
transition_time
can_show_ad_on_death
paused_text
preloads
lobby
context
globalsnode
stats
on_expire
customdata
expired
playertype
teamtype
retain_actor
add_actor_weak_ref
session
on_player_leave
on_team_leave
on_transition_out
has_transitioned_in
has_begun
has_ended
is_transitioning_out
transition_out
create_player
bascenev1._dependency.DependencyComponent
dep_is_present
get_dynamic_deps