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/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/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", "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/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/a6/de/e71297599ee09eee5cdb60b7966a", "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/84/d6/c465935f4ddfdbf4dbece8bd2235", "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/74/10/4cc139ad708ca715a4b434c1f4d3", "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/b4/91/89d0eb1dffc8983107f43509fd26", "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/a4/01/c9221265bdd1e66a82a39257c167", "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/e5/fa/298fe760d4a2805360a2ab29643c", "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/7b/f0/383cdaad06072de360ac9e1b1983", "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/bf/fc/a23ac37afd819f3c9ba33703b458", "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/44/4a/b819a375166fc20d49172fd43c9e", "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/dc/00/7c8757b96a90061bb7bc0adb6e0f", "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/14/68/10beaa487882d09f9a2be90d5e1d" "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: Attributes:
settings settings_raw
The settings dict passed in when the activity was made. 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 teams
The list of ba.Teams in the Activity. This gets populated just before 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 # pylint: disable=too-many-public-methods
# Annotating attr types at the class level lets us introspect them. # Annotating attr types at the class level lets us introspect them.
settings: Dict[str, Any] settings_raw: Dict[str, Any]
teams: List[ba.Team] teams: List[ba.Team]
players: List[ba.Player] players: List[ba.Player]
@ -102,7 +105,9 @@ class Activity(DependencyComponent):
if _ba.getactivity(doraise=False) is not self: if _ba.getactivity(doraise=False) is not self:
raise Exception('invalid context state') 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_transitioned_in = False
self._has_begun = False self._has_begun = False

View File

@ -70,7 +70,7 @@ class CoopGameActivity(GameActivity):
campaign = self.session.campaign campaign = self.session.campaign
assert campaign is not None assert campaign is not None
config_str = (str(len(self.players)) + 'p' + campaign.get_level( 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, _ba.get_scores_to_beat(levelname, config_str,
_general.WeakCall(self._on_got_scores_to_beat)) _general.WeakCall(self._on_got_scores_to_beat))
@ -126,7 +126,8 @@ class CoopGameActivity(GameActivity):
def _get_coop_level_name(self) -> str: def _get_coop_level_name(self) -> str:
assert self.session.campaign is not None 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: def celebrate(self, duration: float) -> None:
"""Tells all existing player-controlled characters to celebrate. """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: def get_instance_display_string(self) -> ba.Lstr:
"""Return a name for this particular game instance.""" """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: def get_instance_scoreboard_display_string(self) -> ba.Lstr:
"""Return a name for this particular game instance. """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. # and can properly translate to 'Anota 3 goles.' in Spanish.
# If we just returned the string 'Score 3 Goals' here, there would # If we just returned the string 'Score 3 Goals' here, there would
# have to be a translation entry for each specific number. ew. # 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 This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced with 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. # and can properly translate to 'anota 3 goles' in Spanish.
# If we just returned the string 'score 3 goals' here, there would # If we just returned the string 'score 3 goals' here, there would
# have to be a translation entry for each specific number. ew. # 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 This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced values then substituted into the result. ${ARG1} will be replaced
@ -816,7 +816,7 @@ class GameActivity(Activity):
subs=subs) subs=subs)
# do some standard filters (epic mode, etc) # 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', translation = Lstr(resource='epicDescriptionFilterText',
subs=[('${DESCRIPTION}', translation)]) subs=[('${DESCRIPTION}', translation)])
vrmode = _ba.app.vr_mode vrmode = _ba.app.vr_mode
@ -1021,9 +1021,9 @@ class GameActivity(Activity):
else: else:
respawn_time = 7.0 respawn_time = 7.0
# if this standard setting is present, factor it in # If this standard setting is present, factor it in
if 'Respawn Times' in self.settings: if 'Respawn Times' in self.settings_raw:
respawn_time *= self.settings['Respawn Times'] respawn_time *= self.settings_raw['Respawn Times']
# we want whole seconds # we want whole seconds
assert respawn_time is not None assert respawn_time is not None

View File

@ -54,4 +54,4 @@ class DrawScoreScreenActivity(MultiTeamScoreScreenActivity):
trail=False, trail=False,
jitter=1.0).autoretain() jitter=1.0).autoretain()
ba.timer(0.35, ba.Call(ba.playsound, self._score_display_sound)) 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))) i * 0.2, shift_time - (i * 0.150 + 0.150)))
ba.timer(i * 0.150 + 0.5, ba.timer(i * 0.150 + 0.5,
ba.Call(ba.playsound, self._score_display_sound_small)) 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 delay = 0.2
if scored: if scored:
delay = 1.2 delay = 1.2

View File

@ -78,7 +78,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
delay3 += 1.5 delay3 += 1.5
ba.timer(0.3, ba.Call(ba.playsound, self._score_display_sound)) 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) assert isinstance(results, ba.TeamGameResults)
self.show_player_scores(delay=0.001, self.show_player_scores(delay=0.001,
results=results, results=results,

View File

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

View File

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

View File

@ -92,7 +92,7 @@ class ChosenOneGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]): def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard from bastd.actor.scoreboard import Scoreboard
super().__init__(settings) super().__init__(settings)
if self.settings['Epic Mode']: if self.settings_raw['Epic Mode']:
self.slow_motion = True self.slow_motion = True
self._scoreboard = Scoreboard() self._scoreboard = Scoreboard()
self._chosen_one_player: Optional[ba.Player] = None self._chosen_one_player: Optional[ba.Player] = None
@ -118,12 +118,13 @@ class ChosenOneGame(ba.TeamGameActivity):
return 'There can be only one.' return 'There can be only one.'
def on_transition_in(self) -> None: def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode'] self.default_music = (ba.MusicType.EPIC
else ba.MusicType.CHOSEN_ONE) if self.settings_raw['Epic Mode'] else
ba.MusicType.CHOSEN_ONE)
super().on_transition_in() super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None: 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() self._update_scoreboard()
def on_player_leave(self, player: ba.Player) -> None: def on_player_leave(self, player: ba.Player) -> None:
@ -133,7 +134,7 @@ class ChosenOneGame(ba.TeamGameActivity):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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.setup_standard_powerup_drops()
self._flag_spawn_pos = self.map.get_flag_position(None) self._flag_spawn_pos = self.map.get_flag_position(None)
self.project_flag_stand(self._flag_spawn_pos) self.project_flag_stand(self._flag_spawn_pos)
@ -243,7 +244,7 @@ class ChosenOneGame(ba.TeamGameActivity):
results = ba.TeamGameResults() results = ba.TeamGameResults()
for team in self.teams: for team in self.teams:
results.set_team_score( results.set_team_score(
team, self.settings['Chosen One Time'] - team, self.settings_raw['Chosen One Time'] -
team.gamedata['time_remaining']) team.gamedata['time_remaining'])
self.end(results=results, announce_delay=0) self.end(results=results, announce_delay=0)
@ -280,10 +281,10 @@ class ChosenOneGame(ba.TeamGameActivity):
self._chosen_one_player = player self._chosen_one_player = player
if player.actor: if player.actor:
if self.settings['Chosen One Gets Shield']: if self.settings_raw['Chosen One Gets Shield']:
player.actor.handlemessage( player.actor.handlemessage(
ba.PowerupMessage('shield')) ba.PowerupMessage('shield'))
if self.settings['Chosen One Gets Gloves']: if self.settings_raw['Chosen One Gets Gloves']:
player.actor.handlemessage( player.actor.handlemessage(
ba.PowerupMessage('punch')) ba.PowerupMessage('punch'))
@ -334,7 +335,8 @@ class ChosenOneGame(ba.TeamGameActivity):
def _update_scoreboard(self) -> None: def _update_scoreboard(self) -> None:
for team in self.teams: for team in self.teams:
self._scoreboard.set_team_value(team, self._scoreboard.set_team_value(
team.gamedata['time_remaining'], team,
self.settings['Chosen One Time'], team.gamedata['time_remaining'],
countdown=True) 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]): def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard from bastd.actor.scoreboard import Scoreboard
super().__init__(settings) super().__init__(settings)
if self.settings['Epic Mode']: if self.settings_raw['Epic Mode']:
self.slow_motion = True self.slow_motion = True
self._scoreboard = Scoreboard() self._scoreboard = Scoreboard()
self._score_sound = ba.getsound('score') self._score_sound = ba.getsound('score')
@ -123,8 +123,9 @@ class ConquestGame(ba.TeamGameActivity):
return 'secure all ${ARG1} flags', len(self.map.flag_points) return 'secure all ${ARG1} flags', len(self.map.flag_points)
def on_transition_in(self) -> None: def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode'] self.default_music = (ba.MusicType.EPIC
else ba.MusicType.GRAND_ROMP) if self.settings_raw['Epic Mode'] else
ba.MusicType.GRAND_ROMP)
super().on_transition_in() super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None: def on_team_join(self, team: ba.Team) -> None:
@ -141,7 +142,7 @@ class ConquestGame(ba.TeamGameActivity):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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.setup_standard_powerup_drops()
# Set up flags with marker lights. # Set up flags with marker lights.

View File

@ -98,7 +98,7 @@ class DeathMatchGame(ba.TeamGameActivity):
def __init__(self, settings: Dict[str, Any]): def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard from bastd.actor.scoreboard import Scoreboard
super().__init__(settings) super().__init__(settings)
if self.settings['Epic Mode']: if self.settings_raw['Epic Mode']:
self.slow_motion = True self.slow_motion = True
# Print messages when players die since it matters here. # 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 return 'kill ${ARG1} enemies', self._score_to_win
def on_transition_in(self) -> None: def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode'] self.default_music = (ba.MusicType.EPIC
else ba.MusicType.TO_THE_DEATH) if self.settings_raw['Epic Mode'] else
ba.MusicType.TO_THE_DEATH)
super().on_transition_in() super().on_transition_in()
def on_team_join(self, team: ba.Team) -> None: def on_team_join(self, team: ba.Team) -> None:
@ -126,14 +127,14 @@ class DeathMatchGame(ba.TeamGameActivity):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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.setup_standard_powerup_drops()
if self.teams: if self.teams:
self._score_to_win = ( 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))) max(1, max(len(t.players) for t in self.teams)))
else: 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() self._update_scoreboard()
def handlemessage(self, msg: Any) -> Any: def handlemessage(self, msg: Any) -> Any:
@ -157,7 +158,7 @@ class DeathMatchGame(ba.TeamGameActivity):
# In free-for-all, killing yourself loses you a point. # In free-for-all, killing yourself loses you a point.
if isinstance(self.session, ba.FreeForAllSession): if isinstance(self.session, ba.FreeForAllSession):
new_score = player.team.gamedata['score'] - 1 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) new_score = max(0, new_score)
player.team.gamedata['score'] = 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]): def __init__(self, settings: Dict[str, Any]):
from bastd.actor.scoreboard import Scoreboard from bastd.actor.scoreboard import Scoreboard
super().__init__(settings) super().__init__(settings)
if self.settings['Epic Mode']: if self.settings_raw['Epic Mode']:
self.slow_motion = True self.slow_motion = True
# Show messages when players die since it's meaningful here. # 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' self.session, ba.DualTeamSession) else 'last one standing wins'
def on_transition_in(self) -> None: def on_transition_in(self) -> None:
self.default_music = (ba.MusicType.EPIC if self.settings['Epic Mode'] self.default_music = (ba.MusicType.EPIC
else ba.MusicType.SURVIVAL) if self.settings_raw['Epic Mode'] else
ba.MusicType.SURVIVAL)
super().on_transition_in() super().on_transition_in()
self._start_time = ba.time() self._start_time = ba.time()
@ -273,7 +274,7 @@ class EliminationGame(ba.TeamGameActivity):
color=(0, 1, 0)) color=(0, 1, 0))
return return
player.gamedata['lives'] = self.settings['Lives Per Player'] player.gamedata['lives'] = self.settings_raw['Lives Per Player']
if self._solo_mode: if self._solo_mode:
player.gamedata['icons'] = [] player.gamedata['icons'] = []
@ -443,7 +444,7 @@ class EliminationGame(ba.TeamGameActivity):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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.setup_standard_powerup_drops()
if self._solo_mode: if self._solo_mode:
self._vs_text = ba.NodeActor( 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 # If balance-team-lives is on, add lives to the smaller team until
# total lives match. # total lives match.
if (isinstance(self.session, ba.DualTeamSession) 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): and self.teams[0].players and self.teams[1].players):
if self._get_total_team_lives( if self._get_total_team_lives(
self.teams[0]) < self._get_total_team_lives(self.teams[1]): 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 self._flag_respawn_light: Optional[ba.NodeActor] = None
def get_instance_description(self) -> Union[str, Sequence]: def get_instance_description(self) -> Union[str, Sequence]:
touchdowns = self.settings['Score to Win'] / 7 touchdowns = self.settings_raw['Score to Win'] / 7
# NOTE: if use just touchdowns = self.settings['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, # and we will need to score, for example, 27 points,
# we will be required to score 3 (not 4) goals .. # we will be required to score 3 (not 4) goals ..
touchdowns = math.ceil(touchdowns) touchdowns = math.ceil(touchdowns)
@ -145,7 +145,7 @@ class FootballTeamGame(ba.TeamGameActivity):
return 'Score a touchdown.' return 'Score a touchdown.'
def get_instance_scoreboard_description(self) -> Union[str, Sequence]: 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) touchdowns = math.ceil(touchdowns)
if touchdowns > 1: if touchdowns > 1:
return 'score ${ARG1} touchdowns', touchdowns return 'score ${ARG1} touchdowns', touchdowns
@ -157,7 +157,7 @@ class FootballTeamGame(ba.TeamGameActivity):
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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.setup_standard_powerup_drops()
self._flag_spawn_pos = (self.map.get_flag_position(None)) self._flag_spawn_pos = (self.map.get_flag_position(None))
self._spawn_flag() self._spawn_flag()
@ -221,7 +221,7 @@ class FootballTeamGame(ba.TeamGameActivity):
50, 50,
big_message=True) big_message=True)
# end game if we won # 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() self.end_game()
ba.playsound(self._score_sound) ba.playsound(self._score_sound)
ba.playsound(self._cheer_sound) ba.playsound(self._cheer_sound)
@ -248,7 +248,7 @@ class FootballTeamGame(ba.TeamGameActivity):
self.end(results=results, announce_delay=0.8) self.end(results=results, announce_delay=0.8)
def _update_scoreboard(self) -> None: 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 assert self._scoreboard is not None
for team in self.teams: for team in self.teams:
self._scoreboard.set_team_value(team, team.gamedata['score'], self._scoreboard.set_team_value(team, team.gamedata['score'],
@ -356,7 +356,7 @@ class FootballCoopGame(ba.CoopGameActivity):
def __init__(self, settings: Dict[str, Any]): def __init__(self, settings: Dict[str, Any]):
settings['map'] = 'Football Stadium' settings['map'] = 'Football Stadium'
super().__init__(settings) super().__init__(settings)
self._preset = self.settings.get('preset', 'rookie') self._preset = self.settings_raw.get('preset', 'rookie')
# Load some media we need. # Load some media we need.
self._cheer_sound = ba.getsound('cheer') self._cheer_sound = ba.getsound('cheer')

View File

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

View File

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

View File

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

View File

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

View File

@ -90,7 +90,7 @@ class NinjaFightGame(ba.TeamGameActivity):
# Called when our game actually begins. # Called when our game actually begins.
def on_begin(self) -> None: def on_begin(self) -> None:
super().on_begin() 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. # In pro mode there's no powerups.
if not is_pro: if not is_pro:

View File

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

View File

@ -75,7 +75,7 @@ class RunaroundGame(ba.CoopGameActivity):
def __init__(self, settings: Dict[str, Any]): def __init__(self, settings: Dict[str, Any]):
settings['map'] = 'Tower D' settings['map'] = 'Tower D'
super().__init__(settings) 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._player_death_sound = ba.getsound('playerDeath')
self._new_wave_sound = ba.getsound('scoreHit01') self._new_wave_sound = ba.getsound('scoreHit01')

View File

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

View File

@ -68,7 +68,7 @@ class TheLastStandGame(ba.CoopGameActivity):
self._tntspawnpos = (0, 5.5, -6) self._tntspawnpos = (0, 5.5, -6)
self._powerup_center = (0, 7, -4.14) self._powerup_center = (0, 7, -4.14)
self._powerup_spread = (7, 2) 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._excludepowerups: List[str] = []
self._scoreboard: Optional[Scoreboard] = None self._scoreboard: Optional[Scoreboard] = None
self._score = 0 self._score = 0

View File

@ -1,5 +1,5 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND --> <!-- 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, <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> 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> <hr>
@ -320,7 +320,7 @@ actually award achievements.</p>
can overlap during transitions.</p> can overlap during transitions.</p>
<h3>Attributes:</h3> <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> <dl>
<dt><h4><a name="attr_ba_Activity__players">players</a></h4></dt><dd> <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> <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> <p> Raises a <a href="#class_ba_SessionNotFoundError">ba.SessionNotFoundError</a> if the Session no longer exists.</p>
</dd> </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><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> </dd>
<dt><h4><a name="attr_ba_Activity__stats">stats</a></h4></dt><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> </p>
<h3>Attributes Inherited:</h3> <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> <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> <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> <dl>
@ -1929,7 +1932,7 @@ its time with lingering corpses, sound effects, etc.</p>
</p> </p>
<h3>Attributes Inherited:</h3> <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> <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> <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> <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># 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># 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> <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 <p>This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced with 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># 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># 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> <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 <p>This way the first string can be consistently translated, with any arg
values then substituted into the result. ${ARG1} will be replaced values then substituted into the result. ${ARG1} will be replaced
@ -4515,7 +4518,7 @@ of the session.</p>
</p> </p>
<h3>Attributes Inherited:</h3> <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> <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> <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> <dl>

View File

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