Changing Activity.settings to Activity.settings_raw to make way for type-safe replacement

This commit is contained in:
Eric Froemling 2020-05-07 13:50:30 -07:00
parent 49d4cf3560
commit cb01f00ed8
26 changed files with 195 additions and 163 deletions

View File

@ -4132,16 +4132,16 @@
"assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c",
"assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb",
"assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe",
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6e/5f/2700a5e06a86a81604894a3b2240",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a6/de/e71297599ee09eee5cdb60b7966a",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/84/d6/c465935f4ddfdbf4dbece8bd2235",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/74/10/4cc139ad708ca715a4b434c1f4d3",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b4/91/89d0eb1dffc8983107f43509fd26",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a4/01/c9221265bdd1e66a82a39257c167",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e5/fa/298fe760d4a2805360a2ab29643c",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/f0/383cdaad06072de360ac9e1b1983",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/bf/fc/a23ac37afd819f3c9ba33703b458",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/44/4a/b819a375166fc20d49172fd43c9e",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/dc/00/7c8757b96a90061bb7bc0adb6e0f",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/14/68/10beaa487882d09f9a2be90d5e1d"
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/32/b0/12e2602010f316e3c26da125bf25",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/50/12/5a87ef4e3b502f1e62f5f2c65985",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/04/0d/5e5e5783775b70d06de5113904d7",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ab/46/fd8487f22aaaf68d310e66c8b5de",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c8/39/04b55a4b918602fbf06dccc4f3c3",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/87/ab/5b265ac08141fae86f6102fb362c",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/13/a7/c2f6454984d5639c39abd5bd871f",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/3a/f67ce2222af11d3ee614ba55e1f0",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/4c/01/f33e921238d1bded473de5964ce4",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/ec/1b/16fa91c7ccba5b20ea9a4ca3e0a4",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/5c/6a/8e947d1317c67dc84856c5649fee",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/7d/aa/901e45f5991e3907f0d9033ccdcf"
}

View File

@ -45,8 +45,11 @@ class Activity(DependencyComponent):
Attributes:
settings
settings_raw
The settings dict passed in when the activity was made.
This attribute is deprecated and should be avoided when possible;
activities should pull all values they need from the 'settings' arg
passed to the Activity __init__ call.
teams
The list of ba.Teams in the Activity. This gets populated just before
@ -64,7 +67,7 @@ class Activity(DependencyComponent):
# pylint: disable=too-many-public-methods
# Annotating attr types at the class level lets us introspect them.
settings: Dict[str, Any]
settings_raw: Dict[str, Any]
teams: List[ba.Team]
players: List[ba.Player]
@ -102,7 +105,9 @@ class Activity(DependencyComponent):
if _ba.getactivity(doraise=False) is not self:
raise Exception('invalid context state')
self.settings = settings
# Should perhaps kill this; activities should validate/store whatever
# settings they need at init time (in a more type-safe way).
self.settings_raw = settings
self._has_transitioned_in = False
self._has_begun = False

View File

@ -70,7 +70,7 @@ class CoopGameActivity(GameActivity):
campaign = self.session.campaign
assert campaign is not None
config_str = (str(len(self.players)) + 'p' + campaign.get_level(
self.settings['name']).get_score_version_string().replace(
self.settings_raw['name']).get_score_version_string().replace(
' ', '_'))
_ba.get_scores_to_beat(levelname, config_str,
_general.WeakCall(self._on_got_scores_to_beat))
@ -126,7 +126,8 @@ class CoopGameActivity(GameActivity):
def _get_coop_level_name(self) -> str:
assert self.session.campaign is not None
return self.session.campaign.name + ':' + str(self.settings['name'])
return self.session.campaign.name + ':' + str(
self.settings_raw['name'])
def celebrate(self, duration: float) -> None:
"""Tells all existing player-controlled characters to celebrate.

View File

@ -370,7 +370,7 @@ class GameActivity(Activity):
def get_instance_display_string(self) -> ba.Lstr:
"""Return a name for this particular game instance."""
return self.get_display_string(self.settings)
return self.get_display_string(self.settings_raw)
def get_instance_scoreboard_display_string(self) -> ba.Lstr:
"""Return a name for this particular game instance.
@ -410,7 +410,7 @@ class GameActivity(Activity):
# 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['Score to Win']]
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
@ -436,7 +436,7 @@ class GameActivity(Activity):
# 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['Score to Win']]
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
@ -816,7 +816,7 @@ class GameActivity(Activity):
subs=subs)
# do some standard filters (epic mode, etc)
if 'Epic Mode' in self.settings and self.settings['Epic Mode']:
if self.settings_raw.get('Epic Mode', False):
translation = Lstr(resource='epicDescriptionFilterText',
subs=[('${DESCRIPTION}', translation)])
vrmode = _ba.app.vr_mode
@ -1021,9 +1021,9 @@ class GameActivity(Activity):
else:
respawn_time = 7.0
# if this standard setting is present, factor it in
if 'Respawn Times' in self.settings:
respawn_time *= self.settings['Respawn Times']
# If this standard setting is present, factor it in
if 'Respawn Times' in self.settings_raw:
respawn_time *= self.settings_raw['Respawn Times']
# we want whole seconds
assert respawn_time is not None

View File

@ -54,4 +54,4 @@ class DrawScoreScreenActivity(MultiTeamScoreScreenActivity):
trail=False,
jitter=1.0).autoretain()
ba.timer(0.35, ba.Call(ba.playsound, self._score_display_sound))
self.show_player_scores(results=self.settings.get('results', None))
self.show_player_scores(results=self.settings_raw.get('results', None))

View File

@ -80,7 +80,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
i * 0.2, shift_time - (i * 0.150 + 0.150)))
ba.timer(i * 0.150 + 0.5,
ba.Call(ba.playsound, self._score_display_sound_small))
scored = (team is self.settings['winner'])
scored = (team is self.settings_raw['winner'])
delay = 0.2
if scored:
delay = 1.2

View File

@ -78,7 +78,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
delay3 += 1.5
ba.timer(0.3, ba.Call(ba.playsound, self._score_display_sound))
results = self.settings['results']
results = self.settings_raw['results']
assert isinstance(results, ba.TeamGameResults)
self.show_player_scores(delay=0.001,
results=results,

View File

@ -63,11 +63,12 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
self._show_up_next = False
self._custom_continue_message = sval
super().on_begin()
winning_team = self.settings['winner']
winning_team = self.settings_raw['winner']
# Pause a moment before playing victory music.
ba.timer(0.6, ba.WeakCall(self._play_victory_music))
ba.timer(4.4, ba.WeakCall(self._show_winner, self.settings['winner']))
ba.timer(4.4,
ba.WeakCall(self._show_winner, self.settings_raw['winner']))
ba.timer(4.6, ba.Call(ba.playsound, self._score_display_sound))
# Score / Name / Player-record.

View File

@ -76,26 +76,27 @@ class AssaultGame(ba.TeamGameActivity):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
self._scoreboard = Scoreboard()
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
self._last_score_time = 0.0
self._score_sound = ba.getsound('score')
self._base_region_materials: Dict[int, ba.Material] = {}
def get_instance_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'Touch the enemy flag.'
return ('Touch the enemy flag ${ARG1} times.',
self.settings['Score to Win'])
self.settings_raw['Score to Win'])
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'touch 1 flag'
return 'touch ${ARG1} flags', self.settings['Score to Win']
return 'touch ${ARG1} flags', self.settings_raw['Score to Win']
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.FORWARD_MARCH)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.FORWARD_MARCH)
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
@ -105,7 +106,7 @@ class AssaultGame(ba.TeamGameActivity):
def on_begin(self) -> None:
from bastd.actor.flag import Flag
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
for team in self.teams:
mat = self._base_region_materials[team.get_id()] = ba.Material()
@ -237,7 +238,7 @@ class AssaultGame(ba.TeamGameActivity):
player_team.gamedata['score'] += 1
self._update_scoreboard()
if (player_team.gamedata['score'] >=
self.settings['Score to Win']):
self.settings_raw['Score to Win']):
self.end_game()
def end_game(self) -> None:
@ -249,4 +250,4 @@ class AssaultGame(ba.TeamGameActivity):
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.gamedata['score'],
self.settings['Score to Win'])
self.settings_raw['Score to Win'])

View File

@ -59,9 +59,9 @@ class CTFFlag(stdflag.Flag):
def reset_return_times(self) -> None:
"""Clear flag related times in the activity."""
self.time_out_respawn_time = int(
self.activity.settings['Flag Idle Return Time'])
self.activity.settings_raw['Flag Idle Return Time'])
self.touch_return_time = float(
self.activity.settings['Flag Touch Return Time'])
self.activity.settings_raw['Flag Touch Return Time'])
@property
def team(self) -> ba.Team:
@ -122,7 +122,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
self._scoreboard = Scoreboard()
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
self._alarmsound = ba.getsound('alarm')
self._ticking_sound = ba.getsound('ticking')
@ -133,19 +133,20 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
self._last_home_flag_notice_print_time = 0.0
def get_instance_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'Steal the enemy flag.'
return ('Steal the enemy flag ${ARG1} times.',
self.settings['Score to Win'])
self.settings_raw['Score to Win'])
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'return 1 flag'
return 'return ${ARG1} flags', self.settings['Score to Win']
return 'return ${ARG1} flags', self.settings_raw['Score to Win']
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.FLAG_CATCHER)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.FLAG_CATCHER)
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
@ -218,7 +219,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
ba.timer(1.0, call=self._tick, repeat=True)
@ -330,7 +331,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
if not reset_team.gamedata['home_flag_at_base']:
reset_team.gamedata['flag'].handlemessage(ba.DieMessage())
reset_team.gamedata['enemy_flag_at_base'] = False
if team.gamedata['score'] >= self.settings['Score to Win']:
if team.gamedata['score'] >= self.settings_raw['Score to Win']:
self.end_game()
def end_game(self) -> None:
@ -390,7 +391,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
for player in team.players:
if player.gamedata['touching_own_flag'] > 0:
return_score = 10 + 5 * int(
self.settings['Flag Touch Return Time'])
self.settings_raw['Flag Touch Return Time'])
self.stats.player_scored(player,
return_score,
screenmessage=False)
@ -418,7 +419,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
# If return-time is zero, just kill it immediately.. otherwise keep
# track of touches and count down.
if float(self.settings['Flag Touch Return Time']) <= 0.0:
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):
@ -496,7 +497,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team, team.gamedata['score'],
self.settings['Score to Win'])
self.settings_raw['Score to Win'])
def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, PlayerSpazDeathMessage):

View File

@ -92,7 +92,7 @@ class ChosenOneGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
self._scoreboard = Scoreboard()
self._chosen_one_player: Optional[ba.Player] = None
@ -118,12 +118,13 @@ class ChosenOneGame(ba.TeamGameActivity):
return 'There can be only one.'
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.CHOSEN_ONE)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.CHOSEN_ONE)
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
team.gamedata['time_remaining'] = self.settings['Chosen One Time']
team.gamedata['time_remaining'] = self.settings_raw['Chosen One Time']
self._update_scoreboard()
def on_player_leave(self, player: ba.Player) -> None:
@ -133,7 +134,7 @@ class ChosenOneGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._flag_spawn_pos = self.map.get_flag_position(None)
self.project_flag_stand(self._flag_spawn_pos)
@ -243,7 +244,7 @@ class ChosenOneGame(ba.TeamGameActivity):
results = ba.TeamGameResults()
for team in self.teams:
results.set_team_score(
team, self.settings['Chosen One Time'] -
team, self.settings_raw['Chosen One Time'] -
team.gamedata['time_remaining'])
self.end(results=results, announce_delay=0)
@ -280,10 +281,10 @@ class ChosenOneGame(ba.TeamGameActivity):
self._chosen_one_player = player
if player.actor:
if self.settings['Chosen One Gets Shield']:
if self.settings_raw['Chosen One Gets Shield']:
player.actor.handlemessage(
ba.PowerupMessage('shield'))
if self.settings['Chosen One Gets Gloves']:
if self.settings_raw['Chosen One Gets Gloves']:
player.actor.handlemessage(
ba.PowerupMessage('punch'))
@ -334,7 +335,8 @@ class ChosenOneGame(ba.TeamGameActivity):
def _update_scoreboard(self) -> None:
for team in self.teams:
self._scoreboard.set_team_value(team,
team.gamedata['time_remaining'],
self.settings['Chosen One Time'],
countdown=True)
self._scoreboard.set_team_value(
team,
team.gamedata['time_remaining'],
self.settings_raw['Chosen One Time'],
countdown=True)

View File

@ -102,7 +102,7 @@ class ConquestGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
self._scoreboard = Scoreboard()
self._score_sound = ba.getsound('score')
@ -123,8 +123,9 @@ class ConquestGame(ba.TeamGameActivity):
return 'secure all ${ARG1} flags', len(self.map.flag_points)
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.GRAND_ROMP)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.GRAND_ROMP)
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
@ -141,7 +142,7 @@ class ConquestGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
# Set up flags with marker lights.

View File

@ -98,7 +98,7 @@ class DeathMatchGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
# Print messages when players die since it matters here.
@ -115,8 +115,9 @@ class DeathMatchGame(ba.TeamGameActivity):
return 'kill ${ARG1} enemies', self._score_to_win
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.TO_THE_DEATH)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.TO_THE_DEATH)
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
@ -126,14 +127,14 @@ class DeathMatchGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
if self.teams:
self._score_to_win = (
self.settings['Kills to Win Per Player'] *
self.settings_raw['Kills to Win Per Player'] *
max(1, max(len(t.players) for t in self.teams)))
else:
self._score_to_win = self.settings['Kills to Win Per Player']
self._score_to_win = self.settings_raw['Kills to Win Per Player']
self._update_scoreboard()
def handlemessage(self, msg: Any) -> Any:
@ -157,7 +158,7 @@ class DeathMatchGame(ba.TeamGameActivity):
# In free-for-all, killing yourself loses you a point.
if isinstance(self.session, ba.FreeForAllSession):
new_score = player.team.gamedata['score'] - 1
if not self.settings['Allow Negative Scores']:
if not self.settings_raw['Allow Negative Scores']:
new_score = max(0, new_score)
player.team.gamedata['score'] = new_score

View File

@ -223,7 +223,7 @@ class EliminationGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard
super().__init__(settings)
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
# Show messages when players die since it's meaningful here.
@ -244,8 +244,9 @@ class EliminationGame(ba.TeamGameActivity):
self.session, ba.DualTeamSession) else 'last one standing wins'
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.SURVIVAL)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.SURVIVAL)
super().on_transition_in()
self._start_time = ba.time()
@ -273,7 +274,7 @@ class EliminationGame(ba.TeamGameActivity):
color=(0, 1, 0))
return
player.gamedata['lives'] = self.settings['Lives Per Player']
player.gamedata['lives'] = self.settings_raw['Lives Per Player']
if self._solo_mode:
player.gamedata['icons'] = []
@ -443,7 +444,7 @@ class EliminationGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
if self._solo_mode:
self._vs_text = ba.NodeActor(
@ -464,7 +465,7 @@ class EliminationGame(ba.TeamGameActivity):
# If balance-team-lives is on, add lives to the smaller team until
# total lives match.
if (isinstance(self.session, ba.DualTeamSession)
and self.settings['Balance Total Lives']
and self.settings_raw['Balance Total Lives']
and self.teams[0].players and self.teams[1].players):
if self._get_total_team_lives(
self.teams[0]) < self._get_total_team_lives(self.teams[1]):

View File

@ -135,8 +135,8 @@ class FootballTeamGame(ba.TeamGameActivity):
self._flag_respawn_light: Optional[ba.NodeActor] = None
def get_instance_description(self) -> Union[str, Sequence]:
touchdowns = self.settings['Score to Win'] / 7
# NOTE: if use just touchdowns = self.settings['Score to Win'] // 7
touchdowns = self.settings_raw['Score to Win'] / 7
# NOTE: if use just touchdowns = self.settings_raw['Score to Win'] // 7
# and we will need to score, for example, 27 points,
# we will be required to score 3 (not 4) goals ..
touchdowns = math.ceil(touchdowns)
@ -145,7 +145,7 @@ class FootballTeamGame(ba.TeamGameActivity):
return 'Score a touchdown.'
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
touchdowns = self.settings['Score to Win'] / 7
touchdowns = self.settings_raw['Score to Win'] / 7
touchdowns = math.ceil(touchdowns)
if touchdowns > 1:
return 'score ${ARG1} touchdowns', touchdowns
@ -157,7 +157,7 @@ class FootballTeamGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._flag_spawn_pos = (self.map.get_flag_position(None))
self._spawn_flag()
@ -221,7 +221,7 @@ class FootballTeamGame(ba.TeamGameActivity):
50,
big_message=True)
# end game if we won
if team.gamedata['score'] >= self.settings['Score to Win']:
if team.gamedata['score'] >= self.settings_raw['Score to Win']:
self.end_game()
ba.playsound(self._score_sound)
ba.playsound(self._cheer_sound)
@ -248,7 +248,7 @@ class FootballTeamGame(ba.TeamGameActivity):
self.end(results=results, announce_delay=0.8)
def _update_scoreboard(self) -> None:
win_score = self.settings['Score to Win']
win_score = self.settings_raw['Score to Win']
assert self._scoreboard is not None
for team in self.teams:
self._scoreboard.set_team_value(team, team.gamedata['score'],
@ -356,7 +356,7 @@ class FootballCoopGame(ba.CoopGameActivity):
def __init__(self, settings: Dict[str, Any]):
settings['map'] = 'Football Stadium'
super().__init__(settings)
self._preset = self.settings.get('preset', 'rookie')
self._preset = self.settings_raw.get('preset', 'rookie')
# Load some media we need.
self._cheer_sound = ba.getsound('cheer')

View File

@ -198,14 +198,14 @@ class HockeyGame(ba.TeamGameActivity):
self._puck: Optional[Puck] = None
def get_instance_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'Score a goal.'
return 'Score ${ARG1} goals.', self.settings['Score to Win']
return 'Score ${ARG1} goals.', self.settings_raw['Score to Win']
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
if self.settings['Score to Win'] == 1:
if self.settings_raw['Score to Win'] == 1:
return 'score a goal'
return 'score ${ARG1} goals', self.settings['Score to Win']
return 'score ${ARG1} goals', self.settings_raw['Score to Win']
def on_transition_in(self) -> None:
self.default_music = ba.MusicType.HOCKEY
@ -214,7 +214,7 @@ class HockeyGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._puck_spawn_pos = self.map.get_flag_position(None)
self._spawn_puck()
@ -299,7 +299,7 @@ class HockeyGame(ba.TeamGameActivity):
big_message=True)
# End game if we won.
if team.gamedata['score'] >= self.settings['Score to Win']:
if team.gamedata['score'] >= self.settings_raw['Score to Win']:
self.end_game()
ba.playsound(self._foghorn_sound)
@ -330,7 +330,7 @@ class HockeyGame(ba.TeamGameActivity):
def _update_scoreboard(self) -> None:
""" update scoreboard and check for winners """
winscore = self.settings['Score to Win']
winscore = self.settings_raw['Score to Win']
for team in self.teams:
self._scoreboard.set_team_value(team, team.gamedata['score'],
winscore)

View File

@ -117,23 +117,23 @@ class KeepAwayGame(ba.TeamGameActivity):
def get_instance_description(self) -> Union[str, Sequence]:
return ('Carry the flag for ${ARG1} seconds.',
self.settings['Hold Time'])
self.settings_raw['Hold Time'])
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
return ('carry the flag for ${ARG1} seconds',
self.settings['Hold Time'])
self.settings_raw['Hold Time'])
def on_transition_in(self) -> None:
self.default_music = ba.MusicType.KEEP_AWAY
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
team.gamedata['time_remaining'] = self.settings['Hold Time']
team.gamedata['time_remaining'] = self.settings_raw['Hold Time']
self._update_scoreboard()
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._flag_spawn_pos = self.map.get_flag_position(None)
self._spawn_flag()
@ -183,8 +183,8 @@ class KeepAwayGame(ba.TeamGameActivity):
results = ba.TeamGameResults()
for team in self.teams:
results.set_team_score(
team,
self.settings['Hold Time'] - team.gamedata['time_remaining'])
team, self.settings_raw['Hold Time'] -
team.gamedata['time_remaining'])
self.end(results=results, announce_delay=0)
def _update_flag_state(self) -> None:
@ -264,7 +264,7 @@ class KeepAwayGame(ba.TeamGameActivity):
for team in self.teams:
self._scoreboard.set_team_value(team,
team.gamedata['time_remaining'],
self.settings['Hold Time'],
self.settings_raw['Hold Time'],
countdown=True)
def handlemessage(self, msg: Any) -> Any:

View File

@ -126,18 +126,18 @@ class KingOfTheHillGame(ba.TeamGameActivity):
def get_instance_description(self) -> Union[str, Sequence]:
return ('Secure the flag for ${ARG1} seconds.',
self.settings['Hold Time'])
self.settings_raw['Hold Time'])
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
return ('secure the flag for ${ARG1} seconds',
self.settings['Hold Time'])
self.settings_raw['Hold Time'])
def on_transition_in(self) -> None:
self.default_music = ba.MusicType.SCARY
super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None:
team.gamedata['time_remaining'] = self.settings['Hold Time']
team.gamedata['time_remaining'] = self.settings_raw['Hold Time']
self._update_scoreboard()
def on_player_join(self, player: ba.Player) -> None:
@ -146,7 +146,7 @@ class KingOfTheHillGame(ba.TeamGameActivity):
def on_begin(self) -> None:
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._flag_pos = self.map.get_flag_position(None)
ba.timer(1.0, self._tick, repeat=True)
@ -222,8 +222,8 @@ class KingOfTheHillGame(ba.TeamGameActivity):
results = ba.TeamGameResults()
for team in self.teams:
results.set_team_score(
team,
self.settings['Hold Time'] - team.gamedata['time_remaining'])
team, self.settings_raw['Hold Time'] -
team.gamedata['time_remaining'])
self.end(results=results, announce_delay=0)
def _update_flag_state(self) -> None:
@ -273,7 +273,7 @@ class KingOfTheHillGame(ba.TeamGameActivity):
for team in self.teams:
self._scoreboard.set_team_value(team,
team.gamedata['time_remaining'],
self.settings['Hold Time'],
self.settings_raw['Hold Time'],
countdown=True)
def handlemessage(self, msg: Any) -> Any:

View File

@ -26,6 +26,7 @@
from __future__ import annotations
import random
from dataclasses import dataclass
from typing import TYPE_CHECKING
import ba
@ -37,6 +38,17 @@ if TYPE_CHECKING:
from bastd.actor.onscreentimer import OnScreenTimer
@dataclass
class GameSettings:
"""Configurable settings for our game."""
epic_mode: bool
@dataclass
class PlayerData:
"""Data we store per player."""
# ba_meta export game
class MeteorShowerGame(ba.TeamGameActivity):
"""Minigame involving dodging falling bombs."""
@ -78,7 +90,7 @@ class MeteorShowerGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]):
super().__init__(settings)
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
# Print messages when players die (since its meaningful in this game).
@ -91,8 +103,9 @@ class MeteorShowerGame(ba.TeamGameActivity):
# Called when our game is transitioning in but not ready to start;
# ..we can go ahead and set our music and whatnot.
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode']
else ba.MusicType.SURVIVAL)
self.default_music = (ba.MusicType.EPIC
if self.settings_raw['Epic Mode'] else
ba.MusicType.SURVIVAL)
super().on_transition_in()
# Called when our game actually starts.
@ -105,13 +118,13 @@ class MeteorShowerGame(ba.TeamGameActivity):
# between waves ..lets have things increase faster if we have fewer
# players.
delay = 5.0 if len(self.players) > 2 else 2.5
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
delay *= 0.25
ba.timer(delay, self._decrement_meteor_time, repeat=True)
# Kick off the first wave in a few seconds.
delay = 3.0
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
delay *= 0.25
ba.timer(delay, self._set_meteor_timer)

View File

@ -90,7 +90,7 @@ class NinjaFightGame(ba.TeamGameActivity):
# Called when our game actually begins.
def on_begin(self) -> None:
super().on_begin()
is_pro = self.settings.get('preset') == 'pro'
is_pro = self.settings_raw.get('preset') == 'pro'
# In pro mode there's no powerups.
if not is_pro:

View File

@ -134,7 +134,7 @@ class RaceGame(ba.TeamGameActivity):
self._race_started = False
super().__init__(settings)
self._scoreboard = Scoreboard()
if self.settings['Epic Mode']:
if self.settings_raw['Epic Mode']:
self.slow_motion = True
self._score_sound = ba.getsound('score')
self._swipsound = ba.getsound('swip')
@ -156,24 +156,24 @@ class RaceGame(ba.TeamGameActivity):
self._bomb_spawn_timer: Optional[ba.Timer] = None
def get_instance_description(self) -> Union[str, Sequence]:
if isinstance(self.session, ba.DualTeamSession) and self.settings.get(
'Entire Team Must Finish', False):
if (isinstance(self.session, ba.DualTeamSession)
and self.settings_raw.get('Entire Team Must Finish', False)):
t_str = ' Your entire team has to finish.'
else:
t_str = ''
if self.settings['Laps'] > 1:
return 'Run ${ARG1} laps.' + t_str, self.settings['Laps']
if self.settings_raw['Laps'] > 1:
return 'Run ${ARG1} laps.' + t_str, self.settings_raw['Laps']
return 'Run 1 lap.' + t_str
def get_instance_scoreboard_description(self) -> Union[str, Sequence]:
if self.settings['Laps'] > 1:
return 'run ${ARG1} laps', self.settings['Laps']
if self.settings_raw['Laps'] > 1:
return 'run ${ARG1} laps', self.settings_raw['Laps']
return 'run 1 lap'
def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC_RACE
if self.settings['Epic Mode'] else
if self.settings_raw['Epic Mode'] else
ba.MusicType.RACE)
super().on_transition_in()
@ -245,15 +245,15 @@ class RaceGame(ba.TeamGameActivity):
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'] = min(self.settings_raw['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'):
if isinstance(
self.session, ba.DualTeamSession
) and self.settings_raw.get('Entire Team Must Finish'):
team.gamedata['lap'] = min(
[p.gamedata['lap'] for p in team.players])
else:
@ -261,7 +261,7 @@ class RaceGame(ba.TeamGameActivity):
[p.gamedata['lap'] for p in team.players])
# A player is finishing.
if player.gamedata['lap'] == self.settings['Laps']:
if player.gamedata['lap'] == self.settings_raw['Laps']:
# In teams mode, hand out points based on the order
# players come in.
@ -285,7 +285,7 @@ class RaceGame(ba.TeamGameActivity):
player.gamedata['distance'] = 9999.0
# If the whole team has finished the race.
if team.gamedata['lap'] == self.settings['Laps']:
if team.gamedata['lap'] == self.settings_raw['Laps']:
ba.playsound(self._score_sound)
player.team.gamedata['finished'] = True
assert self._timer is not None
@ -318,12 +318,12 @@ class RaceGame(ba.TeamGameActivity):
})
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']))])
tstr = ba.Lstr(
resource='lapNumberText',
subs=[('${CURRENT}',
str(player.gamedata['lap'] + 1)),
('${TOTAL}',
str(self.settings_raw['Laps']))])
txtnode = ba.newnode('text',
owner=mathnode,
attrs={
@ -365,7 +365,7 @@ class RaceGame(ba.TeamGameActivity):
# is on (otherwise in teams mode everyone could just leave except the
# leading player to win).
if (isinstance(self.session, ba.DualTeamSession)
and self.settings.get('Entire Team Must Finish')):
and self.settings_raw.get('Entire Team Must Finish')):
ba.screenmessage(ba.Lstr(
translate=('statements',
'${TEAM} is disqualified because ${PLAYER} left'),
@ -397,21 +397,21 @@ class RaceGame(ba.TeamGameActivity):
teams_dist = 0
else:
if (isinstance(self.session, ba.DualTeamSession)
and self.settings.get('Entire Team Must Finish')):
and self.settings_raw.get('Entire Team Must Finish')):
teams_dist = min(distances)
else:
teams_dist = max(distances)
self._scoreboard.set_team_value(
team,
teams_dist,
self.settings['Laps'],
flash=(teams_dist >= float(self.settings['Laps'])),
self.settings_raw['Laps'],
flash=(teams_dist >= float(self.settings_raw['Laps'])),
show_value=False)
def on_begin(self) -> None:
from bastd.actor.onscreentimer import OnScreenTimer
super().on_begin()
self.setup_standard_time_limit(self.settings['Time Limit'])
self.setup_standard_time_limit(self.settings_raw['Time Limit'])
self.setup_standard_powerup_drops()
self._team_finish_pts = 100
@ -431,14 +431,14 @@ class RaceGame(ba.TeamGameActivity):
}))
self._timer = OnScreenTimer()
if self.settings['Mine Spawning'] != 0:
if self.settings_raw['Mine Spawning'] != 0:
self._race_mines = [
RaceMine(point=p, mine=None)
for p in self.map.get_def_points('race_mine')
]
if self._race_mines:
self._race_mine_timer = ba.Timer(
0.001 * self.settings['Mine Spawning'],
0.001 * self.settings_raw['Mine Spawning'],
self._update_race_mine,
repeat=True)
@ -518,11 +518,11 @@ class RaceGame(ba.TeamGameActivity):
assert self._timer is not None
self._timer.start()
if self.settings['Bomb Spawning'] != 0:
self._bomb_spawn_timer = ba.Timer(0.001 *
self.settings['Bomb Spawning'],
self._spawn_bomb,
repeat=True)
if self.settings_raw['Bomb Spawning'] != 0:
self._bomb_spawn_timer = ba.Timer(
0.001 * self.settings_raw['Bomb Spawning'],
self._spawn_bomb,
repeat=True)
self._race_started = True

View File

@ -75,7 +75,7 @@ class RunaroundGame(ba.CoopGameActivity):
def __init__(self, settings: Dict[str, Any]):
settings['map'] = 'Tower D'
super().__init__(settings)
self._preset = self.settings.get('preset', 'pro')
self._preset = self.settings_raw.get('preset', 'pro')
self._player_death_sound = ba.getsound('playerDeath')
self._new_wave_sound = ba.getsound('scoreHit01')

View File

@ -95,7 +95,7 @@ class TargetPracticeGame(ba.TeamGameActivity):
self.update_scoreboard()
# Number of targets is based on player count.
num_targets = self.settings['Target Count']
num_targets = self.settings_raw['Target Count']
for i in range(num_targets):
ba.timer(5.0 + i * 1.0, self._spawn_target)
@ -114,9 +114,9 @@ class TargetPracticeGame(ba.TeamGameActivity):
# Give players permanent triple impact bombs and wire them up
# to tell us when they drop a bomb.
if self.settings['Enable Impact Bombs']:
if self.settings_raw['Enable Impact Bombs']:
spaz.bomb_type = 'impact'
if self.settings['Enable Triple Bombs']:
if self.settings_raw['Enable Triple Bombs']:
spaz.set_bomb_count(3)
spaz.add_dropped_bomb_callback(self._on_spaz_dropped_bomb)
return spaz

View File

@ -68,7 +68,7 @@ class TheLastStandGame(ba.CoopGameActivity):
self._tntspawnpos = (0, 5.5, -6)
self._powerup_center = (0, 7, -4.14)
self._powerup_spread = (7, 2)
self._preset = self.settings.get('preset', 'default')
self._preset = self.settings_raw.get('preset', 'default')
self._excludepowerups: List[str] = []
self._scoreboard: Optional[Scoreboard] = None
self._score = 0

View File

@ -1,5 +1,5 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
<h4><em>last updated on 2020-05-07 for Ballistica version 1.5.0 build 20015</em></h4>
<h4><em>last updated on 2020-05-07 for Ballistica version 1.5.0 build 20016</em></h4>
<p>This page documents the Python classes and functions in the 'ba' module,
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
<hr>
@ -320,7 +320,7 @@ actually award achievements.</p>
can overlap during transitions.</p>
<h3>Attributes:</h3>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__session">session</a>, <a href="#attr_ba_Activity__settings">settings</a>, <a href="#attr_ba_Activity__stats">stats</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__session">session</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__stats">stats</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<dl>
<dt><h4><a name="attr_ba_Activity__players">players</a></h4></dt><dd>
<p><span>List[<a href="#class_ba_Player">ba.Player</a>]</span></p>
@ -336,9 +336,12 @@ join or leave the game.</p>
<p> Raises a <a href="#class_ba_SessionNotFoundError">ba.SessionNotFoundError</a> if the Session no longer exists.</p>
</dd>
<dt><h4><a name="attr_ba_Activity__settings">settings</a></h4></dt><dd>
<dt><h4><a name="attr_ba_Activity__settings_raw">settings_raw</a></h4></dt><dd>
<p><span>Dict[str, Any]</span></p>
<p>The settings dict passed in when the activity was made.</p>
<p>The settings dict passed in when the activity was made.
This attribute is deprecated and should be avoided when possible;
activities should pull all values they need from the 'settings' arg
passed to the Activity __init__ call.</p>
</dd>
<dt><h4><a name="attr_ba_Activity__stats">stats</a></h4></dt><dd>
@ -1426,7 +1429,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
</p>
<h3>Attributes Inherited:</h3>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings">settings</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h3>Attributes Defined Here:</h3>
<h5><a href="#attr_ba_CoopGameActivity__map">map</a>, <a href="#attr_ba_CoopGameActivity__session">session</a>, <a href="#attr_ba_CoopGameActivity__stats">stats</a></h5>
<dl>
@ -1929,7 +1932,7 @@ its time with lingering corpses, sound effects, etc.</p>
</p>
<h3>Attributes Inherited:</h3>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings">settings</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h3>Attributes Defined Here:</h3>
<h5><a href="#attr_ba_GameActivity__map">map</a>, <a href="#attr_ba_GameActivity__session">session</a>, <a href="#attr_ba_GameActivity__stats">stats</a></h5>
<dl>
@ -2072,7 +2075,7 @@ form instead of just a string:</p>
<span><em><small># and can properly translate to 'Anota 3 goles.' in Spanish.</small></em></span>
<span><em><small># If we just returned the string 'Score 3 Goals' here, there would</small></em></span>
<span><em><small># have to be a translation entry for each specific number. ew.</small></em></span>
return ['Score ${ARG1} goals.', self.settings['Score to Win']]</pre>
return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]</pre>
<p>This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced with
@ -2105,7 +2108,7 @@ instead of just a string:</p>
<span><em><small># and can properly translate to 'anota 3 goles' in Spanish.</small></em></span>
<span><em><small># If we just returned the string 'score 3 goals' here, there would</small></em></span>
<span><em><small># have to be a translation entry for each specific number. ew.</small></em></span>
return ['score ${ARG1} goals', self.settings['Score to Win']]</pre>
return ['score ${ARG1} goals', self.settings_raw['Score to Win']]</pre>
<p>This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced
@ -4515,7 +4518,7 @@ of the session.</p>
</p>
<h3>Attributes Inherited:</h3>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings">settings</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h5><a href="#attr_ba_Activity__players">players</a>, <a href="#attr_ba_Activity__settings_raw">settings_raw</a>, <a href="#attr_ba_Activity__teams">teams</a></h5>
<h3>Attributes Defined Here:</h3>
<h5><a href="#attr_ba_TeamGameActivity__map">map</a>, <a href="#attr_ba_TeamGameActivity__session">session</a>, <a href="#attr_ba_TeamGameActivity__stats">stats</a></h5>
<dl>

View File

@ -36,12 +36,14 @@ import sys
from typing import TYPE_CHECKING
# Pull in some standard snippets we want to expose.
# pylint: disable=unused-import
# noinspection PyUnresolvedReferences
from efrotools.snippets import ( # pylint: disable=unused-import
from efrotools.snippets import (
PROJROOT, snippets_main, formatcode, formatscripts, formatmakefile,
cpplint, pylint, mypy, dmypy, tool_config_install, sync, sync_all,
scriptfiles, pycharm, clioncode, androidstudiocode, makefile_target_list,
spelling, spelling_all, compile_python_files, pytest)
# pylint: enable=unused-import
if TYPE_CHECKING:
from typing import Optional