From 3ff115272f68625c8201881709712ed0c8864194 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Tue, 19 May 2020 17:27:40 -0700 Subject: [PATCH] Added shorthand ways to define some game attrs --- assets/src/ba_data/python/ba/_coopsession.py | 4 +- assets/src/ba_data/python/ba/_gameactivity.py | 59 ++++-- assets/src/ba_data/python/ba/_playlist.py | 2 +- .../src/ba_data/python/bastd/game/assault.py | 69 +++--- .../python/bastd/game/capturetheflag.py | 78 +++---- .../ba_data/python/bastd/game/chosenone.py | 78 +++---- .../src/ba_data/python/bastd/game/conquest.py | 53 ++--- .../ba_data/python/bastd/game/deathmatch.py | 59 +++--- .../python/bastd/game/easteregghunt.py | 23 +- .../ba_data/python/bastd/game/elimination.py | 46 ++-- .../src/ba_data/python/bastd/game/football.py | 69 +++--- .../src/ba_data/python/bastd/game/hockey.py | 52 ++--- .../src/ba_data/python/bastd/game/keepaway.py | 87 ++++---- .../python/bastd/game/kingofthehill.py | 114 +++++----- .../ba_data/python/bastd/game/meteorshower.py | 34 +-- .../ba_data/python/bastd/game/ninjafight.py | 18 +- .../ba_data/python/bastd/game/onslaught.py | 15 +- assets/src/ba_data/python/bastd/game/race.py | 50 ++--- .../ba_data/python/bastd/game/runaround.py | 10 +- .../python/bastd/game/targetpractice.py | 51 ++--- .../ba_data/python/bastd/game/thelaststand.py | 19 +- .../python/bastd/ui/playlist/editgame.py | 2 +- docs/ba_module.md | 198 +++++++++--------- 23 files changed, 511 insertions(+), 679 deletions(-) diff --git a/assets/src/ba_data/python/ba/_coopsession.py b/assets/src/ba_data/python/ba/_coopsession.py index b6c008ec..569aecc9 100644 --- a/assets/src/ba_data/python/ba/_coopsession.py +++ b/assets/src/ba_data/python/ba/_coopsession.py @@ -124,7 +124,7 @@ class CoopSession(Session): settings = level.get_settings() # Make sure all settings the game expects are present. - neededsettings = gametype.get_settings(type(self)) + neededsettings = gametype.get_game_settings(type(self)) for settingname, setting in neededsettings: if settingname not in settings: settings[settingname] = setting['default'] @@ -147,7 +147,7 @@ class CoopSession(Session): settings = nextlevel.get_settings() # Make sure all settings the game expects are present. - neededsettings = gametype.get_settings(type(self)) + neededsettings = gametype.get_game_settings(type(self)) for settingname, setting in neededsettings: if settingname not in settings: settings[settingname] = setting['default'] diff --git a/assets/src/ba_data/python/ba/_gameactivity.py b/assets/src/ba_data/python/ba/_gameactivity.py index e59ff9fb..d8f62401 100644 --- a/assets/src/ba_data/python/ba/_gameactivity.py +++ b/assets/src/ba_data/python/ba/_gameactivity.py @@ -51,6 +51,18 @@ class GameActivity(Activity[PlayerType, TeamType]): tips: List[Union[str, Dict[str, Any]]] = [] + # Default get_name() will return this if not None. + name: Optional[str] = None + + # Default get_description() will return this if not None. + description: Optional[str] = None + + # Default get_game_settings() will return this if not None. + game_settings: Optional[List[Tuple[str, Dict[str, Any]]]] = None + + # Default get_score_info() will return this if not None. + score_info: Optional[ba.ScoreInfo] = None + @classmethod def create_config_ui( cls, @@ -69,9 +81,9 @@ class GameActivity(Activity[PlayerType, TeamType]): success or None on cancel. Generally subclasses don't need to override this; if they override - ba.GameActivity.get_settings() and ba.GameActivity.get_supported_maps() - they can just rely on the default implementation here which calls those - methods. + ba.GameActivity.get_game_settings() and + ba.GameActivity.get_supported_maps() they can just rely on + the default implementation here which calls those methods. """ delegate = _ba.app.delegate assert delegate is not None @@ -81,15 +93,15 @@ class GameActivity(Activity[PlayerType, TeamType]): @classmethod def get_score_info(cls) -> ba.ScoreInfo: """Return info about game scoring setup; can be overridden by games.""" - return ScoreInfo() + return cls.score_info if cls.score_info is not None else ScoreInfo() @classmethod def get_name(cls) -> str: - """Return a str name for this game type.""" - try: - return cls.__module__.replace('_', ' ') - except Exception: - return 'Untitled Game' + """Return a str name for this game type. + + This default implementation simply returns the 'name' class attr. + """ + return cls.name if cls.name is not None else 'Untitled Game' @classmethod def get_display_string(cls, settings: Optional[Dict] = None) -> ba.Lstr: @@ -119,13 +131,14 @@ class GameActivity(Activity[PlayerType, TeamType]): @classmethod def get_description(cls, sessiontype: Type[ba.Session]) -> str: - """ - Subclasses should override this to return a description for this - activity type (in English) within the context of the given - ba.Session type. + """Get a str description of this game type. + + The default implementation simply returns the 'description' class var. + Classes which want to change their description depending on the session + can override this method. """ del sessiontype # unused arg - return '' + return cls.description if cls.description is not None else '' @classmethod def get_description_display_string( @@ -138,7 +151,7 @@ class GameActivity(Activity[PlayerType, TeamType]): return Lstr(translate=('gameDescriptions', description)) @classmethod - def get_settings( + def get_game_settings( cls, sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: """ @@ -162,9 +175,9 @@ class GameActivity(Activity[PlayerType, TeamType]): 'increment': Value increment for int/float settings. - # example get_settings() implementation for a capture-the-flag game: + # example get_game_settings() for a capture-the-flag game: @classmethod - def get_settings(cls,sessiontype): + def get_game_settings(cls, sessiontype): return [("Score to Win", { 'default': 3, 'min_value': 1 @@ -199,7 +212,7 @@ class GameActivity(Activity[PlayerType, TeamType]): })] """ del sessiontype # Unused arg. - return [] + return [] if cls.game_settings is None else cls.game_settings @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: @@ -353,7 +366,7 @@ class GameActivity(Activity[PlayerType, TeamType]): This is shown in the center of the screen below the game name at the start of a game. It should start with a capital letter and end with a period, and can be a bit more verbose than the version returned by - get_instance_scoreboard_description(). + get_instance_description_short(). Note that translation is applied by looking up the specific returned value as a key, so the number of returned variations should be limited; @@ -361,7 +374,7 @@ class GameActivity(Activity[PlayerType, TeamType]): description, you can return a sequence of values in the following form instead of just a string: - # this will give us something like 'Score 3 goals.' in English + # This will give us something like 'Score 3 goals.' in English # and can properly translate to 'Anota 3 goles.' in Spanish. # If we just returned the string 'Score 3 Goals' here, there would # have to be a translation entry for each specific number. ew. @@ -373,7 +386,7 @@ class GameActivity(Activity[PlayerType, TeamType]): """ return self.get_description(type(self.session)) - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: """Return a short description for this game instance in English. This description is used above the game scoreboard in the @@ -387,7 +400,7 @@ class GameActivity(Activity[PlayerType, TeamType]): description, you can return a sequence of values in the following form instead of just a string: - # this will give us something like 'score 3 goals' in English + # This will give us something like 'score 3 goals' in English # and can properly translate to 'anota 3 goles' in Spanish. # If we just returned the string 'score 3 goals' here, there would # have to be a translation entry for each specific number. ew. @@ -669,7 +682,7 @@ class GameActivity(Activity[PlayerType, TeamType]): # the description can be either a string or a sequence with args # to swap in post-translation - sb_desc_in = self.get_instance_scoreboard_description() + sb_desc_in = self.get_instance_description_short() sb_desc_l: Sequence if isinstance(sb_desc_in, str): sb_desc_l = [sb_desc_in] # handle simple string case diff --git a/assets/src/ba_data/python/ba/_playlist.py b/assets/src/ba_data/python/ba/_playlist.py index b50b1c6c..1786ee21 100644 --- a/assets/src/ba_data/python/ba/_playlist.py +++ b/assets/src/ba_data/python/ba/_playlist.py @@ -151,7 +151,7 @@ def filter_playlist(playlist: PlaylistType, entry['is_unowned_game'] = True # Make sure all settings the game defines are present. - neededsettings = gameclass.get_settings(sessiontype) + neededsettings = gameclass.get_game_settings(sessiontype) for setting_name, setting in neededsettings: if (setting_name not in entry['settings'] and 'default' in setting): diff --git a/assets/src/ba_data/python/bastd/game/assault.py b/assets/src/ba_data/python/bastd/game/assault.py index c7542650..334571df 100644 --- a/assets/src/ba_data/python/bastd/game/assault.py +++ b/assets/src/ba_data/python/bastd/game/assault.py @@ -26,7 +26,6 @@ from __future__ import annotations import random -from dataclasses import dataclass from typing import TYPE_CHECKING import ba @@ -34,33 +33,48 @@ from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage from bastd.actor.flag import Flag if TYPE_CHECKING: - from typing import Any, Type, List, Dict, Tuple, Sequence, Union + from typing import Any, Type, List, Dict, Sequence, Union -@dataclass(eq=False) class Player(ba.Player['Team']): """Our player type for this game.""" -@dataclass(eq=False) class Team(ba.Team[Player]): """Our team type for this game.""" - base_pos: Sequence[float] - flag: Flag - score: int = 0 + + def __init__(self, base_pos: Sequence[float], flag: Flag) -> None: + self.base_pos = base_pos + self.flag = flag + self.score = 0 # ba_meta export game class AssaultGame(ba.TeamGameActivity[Player, Team]): """Game where you score by touching the other team's flag.""" - @classmethod - def get_name(cls) -> str: - return 'Assault' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Reach the enemy flag to score.' + name = 'Assault' + description = 'Reach the enemy flag to score.' + game_settings = [ + ('Score to Win', { + 'min_value': 1, + 'default': 3 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ('Epic Mode', { + 'default': False + }), + ] @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -70,31 +84,6 @@ class AssaultGame(ba.TeamGameActivity[Player, Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('team_flag') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Score to Win', { - 'min_value': 1, - 'default': 3 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }), - ('Epic Mode', { - 'default': False - }), - ] - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) @@ -116,7 +105,7 @@ class AssaultGame(ba.TeamGameActivity[Player, Team]): return 'Touch the enemy flag.' return 'Touch the enemy flag ${ARG1} times.', self._score_to_win - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: if self._score_to_win == 1: return 'touch 1 flag' return 'touch ${ARG1} flags', self._score_to_win diff --git a/assets/src/ba_data/python/bastd/game/capturetheflag.py b/assets/src/ba_data/python/bastd/game/capturetheflag.py index c190da31..99f617b4 100644 --- a/assets/src/ba_data/python/bastd/game/capturetheflag.py +++ b/assets/src/ba_data/python/bastd/game/capturetheflag.py @@ -34,7 +34,7 @@ from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: - from typing import Any, Type, List, Dict, Tuple, Sequence, Union, Optional + from typing import Any, Type, List, Dict, Sequence, Union, Optional class CTFFlag(stdflag.Flag): @@ -110,13 +110,38 @@ class Team(ba.Team[Player]): class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): """Game of stealing other team's flag and returning it to your base.""" - @classmethod - def get_name(cls) -> str: - return 'Capture the Flag' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Return the enemy flag to score.' + name = 'Capture the Flag' + description = 'Return the enemy flag to score.' + game_settings = [ + ('Score to Win', { + 'min_value': 1, + 'default': 3 + }), + ('Flag Touch Return Time', { + 'min_value': 0, + 'default': 0, + 'increment': 1 + }), + ('Flag Idle Return Time', { + 'min_value': 5, + 'default': 30, + 'increment': 5 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ('Epic Mode', { + 'default': False + }), + ] @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -126,41 +151,6 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('team_flag') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Score to Win', { - 'min_value': 1, - 'default': 3 - }), - ('Flag Touch Return Time', { - 'min_value': 0, - 'default': 0, - 'increment': 1 - }), - ('Flag Idle Return Time', { - 'min_value': 5, - 'default': 30, - 'increment': 5 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }), - ('Epic Mode', { - 'default': False - }), - ] - def __init__(self, settings: Dict[str, Any]): super().__init__(settings) self._scoreboard = Scoreboard() @@ -192,7 +182,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): return 'Steal the enemy flag.' return 'Steal the enemy flag ${ARG1} times.', self._score_to_win - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: if self._score_to_win == 1: return 'return 1 flag' return 'return ${ARG1} flags', self._score_to_win diff --git a/assets/src/ba_data/python/bastd/game/chosenone.py b/assets/src/ba_data/python/bastd/game/chosenone.py index 92fd55b0..db166dc0 100644 --- a/assets/src/ba_data/python/bastd/game/chosenone.py +++ b/assets/src/ba_data/python/bastd/game/chosenone.py @@ -32,8 +32,7 @@ from bastd.actor.flag import Flag from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage if TYPE_CHECKING: - from typing import (Any, Type, List, Dict, Tuple, Optional, Sequence, - Union) + from typing import Any, Type, List, Dict, Optional, Sequence, Union @dataclass(eq=False) @@ -56,55 +55,42 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]): kill you and become the chosen one themselves. """ - @classmethod - def get_name(cls) -> str: - return 'Chosen One' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Time Held') - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return ('Be the chosen one for a length of time to win.\n' - 'Kill the chosen one to become it.') + name = 'Chosen One' + description = ('Be the chosen one for a length of time to win.\n' + 'Kill the chosen one to become it.') + game_settings = [ + ('Chosen One Time', { + 'min_value': 10, + 'default': 30, + 'increment': 10 + }), + ('Chosen One Gets Gloves', { + 'default': True + }), + ('Chosen One Gets Shield', { + 'default': False + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ('Epic Mode', { + 'default': False + }), + ] + score_info = ba.ScoreInfo(label='Time Held') @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('keep_away') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Chosen One Time', { - 'min_value': 10, - 'default': 30, - 'increment': 10 - }), - ('Chosen One Gets Gloves', { - 'default': True - }), - ('Chosen One Gets Shield', { - 'default': False - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }), - ('Epic Mode', { - 'default': False - }), - ] - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) diff --git a/assets/src/ba_data/python/bastd/game/conquest.py b/assets/src/ba_data/python/bastd/game/conquest.py index 361039bb..b459e147 100644 --- a/assets/src/ba_data/python/bastd/game/conquest.py +++ b/assets/src/ba_data/python/bastd/game/conquest.py @@ -33,8 +33,7 @@ from bastd.actor.flag import Flag from bastd.actor.playerspaz import PlayerSpazDeathMessage if TYPE_CHECKING: - from typing import (Any, Optional, Type, List, Tuple, Dict, Sequence, - Union) + from typing import Any, Optional, Type, List, Dict, Sequence, Union class ConquestFlag(Flag): @@ -60,13 +59,24 @@ class ConquestFlag(Flag): class ConquestGame(ba.TeamGameActivity[ba.Player, ba.Team]): """A game where teams try to claim all flags on the map.""" - @classmethod - def get_name(cls) -> str: - return 'Conquest' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Secure all flags on the map to win.' + name = 'Conquest' + description = 'Secure all flags on the map to win.' + game_settings = [ + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ('Epic Mode', { + 'default': False + }), + ] @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -76,29 +86,6 @@ class ConquestGame(ba.TeamGameActivity[ba.Player, ba.Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('conquest') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), - ('2 Minutes', 120), - ('5 Minutes', 300), - ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), - ('Short', 0.5), - ('Normal', 1.0), - ('Long', 2.0), - ('Longer', 4.0)], - 'default': 1.0 - }), - ('Epic Mode', {'default': False})] # yapf: disable - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) @@ -119,7 +106,7 @@ class ConquestGame(ba.TeamGameActivity[ba.Player, ba.Team]): def get_instance_description(self) -> Union[str, Sequence]: return 'Secure all ${ARG1} flags.', len(self.map.flag_points) - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: return 'secure all ${ARG1} flags', len(self.map.flag_points) def on_transition_in(self) -> None: diff --git a/assets/src/ba_data/python/bastd/game/deathmatch.py b/assets/src/ba_data/python/bastd/game/deathmatch.py index e6d64d2e..e2f37062 100644 --- a/assets/src/ba_data/python/bastd/game/deathmatch.py +++ b/assets/src/ba_data/python/bastd/game/deathmatch.py @@ -38,25 +38,14 @@ if TYPE_CHECKING: class DeathMatchGame(ba.TeamGameActivity[ba.Player, ba.Team]): """A game type based on acquiring kills.""" - @classmethod - def get_name(cls) -> str: - return 'Death Match' + name = 'Death Match' + description = 'Kill a set number of enemies to win.' + + # Print messages when players die since it matters here. + announce_player_deaths = True @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Kill a set number of enemies to win.' - - @classmethod - def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: - return (issubclass(sessiontype, ba.DualTeamSession) - or issubclass(sessiontype, ba.FreeForAllSession)) - - @classmethod - def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: - return ba.getmaps('melee') - - @classmethod - def get_settings( + def get_game_settings( cls, sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: settings: List[Tuple[str, Dict[str, Any]]] = [ @@ -66,24 +55,20 @@ class DeathMatchGame(ba.TeamGameActivity[ba.Player, ba.Team]): 'increment': 1 }), ('Time Limit', { - 'choices': - [('None', 0), - ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 }), ('Respawn Times', { - 'choices': - [('Shorter', 0.25), ('Short', 0.5), - ('Normal', 1.0), ('Long', 2.0), - ('Longer', 4.0)], - 'default': 1.0 + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 }), ('Epic Mode', { 'default': False - }) - ] # yapf: disable + }), + ] # In teams mode, a suicide gives a point to the other team, but in # free-for-all it subtracts from your own score. By default we clamp @@ -95,15 +80,21 @@ class DeathMatchGame(ba.TeamGameActivity[ba.Player, ba.Team]): return settings + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return (issubclass(sessiontype, ba.DualTeamSession) + or issubclass(sessiontype, ba.FreeForAllSession)) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ba.getmaps('melee') + def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) if self.settings_raw['Epic Mode']: self.slow_motion = True - # Print messages when players die since it matters here. - self.announce_player_deaths = True - self._scoreboard = Scoreboard() self._score_to_win = None self._dingsound = ba.getsound('dingSmall') @@ -111,7 +102,7 @@ class DeathMatchGame(ba.TeamGameActivity[ba.Player, ba.Team]): def get_instance_description(self) -> Union[str, Sequence]: return 'Crush ${ARG1} of your enemies.', self._score_to_win - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: return 'kill ${ARG1} enemies', self._score_to_win def on_transition_in(self) -> None: diff --git a/assets/src/ba_data/python/bastd/game/easteregghunt.py b/assets/src/ba_data/python/bastd/game/easteregghunt.py index 6a68eeff..79e5382b 100644 --- a/assets/src/ba_data/python/bastd/game/easteregghunt.py +++ b/assets/src/ba_data/python/bastd/game/easteregghunt.py @@ -33,6 +33,7 @@ from bastd.actor import bomb from bastd.actor import playerspaz from bastd.actor import spazbot from bastd.actor.onscreencountdown import OnScreenCountdown +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Type, Dict, List, Tuple, Optional @@ -42,17 +43,10 @@ if TYPE_CHECKING: class EasterEggHuntGame(ba.TeamGameActivity[ba.Player, ba.Team]): """A game where score is based on collecting eggs.""" - @classmethod - def get_name(cls) -> str: - return 'Easter Egg Hunt' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Score', scoretype=ba.ScoreType.POINTS) - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Gather eggs!' + name = 'Easter Egg Hunt' + description = 'Gather eggs!' + game_settings = [('Pro Mode', {'default': False})] + score_info = ba.ScoreInfo(label='Score', scoretype=ba.ScoreType.POINTS) # We're currently hard-coded for one map. @classmethod @@ -66,14 +60,7 @@ class EasterEggHuntGame(ba.TeamGameActivity[ba.Player, ba.Team]): or issubclass(sessiontype, ba.DualTeamSession) or issubclass(sessiontype, ba.FreeForAllSession)) - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [('Pro Mode', {'default': False})] - def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._last_player_death_time = None self._scoreboard = Scoreboard() diff --git a/assets/src/ba_data/python/bastd/game/elimination.py b/assets/src/ba_data/python/bastd/game/elimination.py index cb805901..ffe07ce3 100644 --- a/assets/src/ba_data/python/bastd/game/elimination.py +++ b/assets/src/ba_data/python/bastd/game/elimination.py @@ -182,31 +182,16 @@ class Team(ba.Team[Player]): class EliminationGame(ba.TeamGameActivity[Player, Team]): """Game type where last player(s) left alive win.""" - @classmethod - def get_name(cls) -> str: - return 'Elimination' + name = 'Elimination' + description = 'Last remaining alive wins.' + score_info = ba.ScoreInfo(label='Survived', + scoretype=ba.ScoreType.SECONDS, + none_is_winner=True) + # Show messages when players die since it's meaningful here. + announce_player_deaths = True @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Survived', - scoretype=ba.ScoreType.SECONDS, - none_is_winner=True) - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Last remaining alive wins.' - - @classmethod - def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: - return (issubclass(sessiontype, ba.DualTeamSession) - or issubclass(sessiontype, ba.FreeForAllSession)) - - @classmethod - def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: - return ba.getmaps('melee') - - @classmethod - def get_settings( + def get_game_settings( cls, sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: settings: List[Tuple[str, Dict[str, Any]]] = [ @@ -231,13 +216,20 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]): 'default': False }), ] - if issubclass(sessiontype, ba.DualTeamSession): settings.append(('Solo Mode', {'default': False})) settings.append(('Balance Total Lives', {'default': False})) - return settings + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return (issubclass(sessiontype, ba.DualTeamSession) + or issubclass(sessiontype, ba.FreeForAllSession)) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ba.getmaps('melee') + def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) @@ -253,8 +245,6 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]): self._solo_mode = bool(settings.get('Solo Mode', False)) # Base class overrides: - # Show messages when players die since it's meaningful here. - self.announce_player_deaths = True self.slow_motion = self._epic_mode self.default_music = (ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SURVIVAL) @@ -263,7 +253,7 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]): return 'Last team standing wins.' if isinstance( self.session, ba.DualTeamSession) else 'Last one standing wins.' - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: return 'last team standing wins' if isinstance( self.session, ba.DualTeamSession) else 'last one standing wins' diff --git a/assets/src/ba_data/python/bastd/game/football.py b/assets/src/ba_data/python/bastd/game/football.py index be96698c..d8cdbccc 100644 --- a/assets/src/ba_data/python/bastd/game/football.py +++ b/assets/src/ba_data/python/bastd/game/football.py @@ -38,8 +38,7 @@ from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: - from typing import (Any, List, Tuple, Type, Dict, Sequence, Optional, - Union) + from typing import Any, List, Type, Dict, Sequence, Optional, Union from bastd.actor.spaz import Spaz @@ -81,46 +80,36 @@ class Team(ba.Team[Player]): class FootballTeamGame(ba.TeamGameActivity[Player, Team]): """Football game for teams mode.""" - @classmethod - def get_name(cls) -> str: - return 'Football' + name = 'Football' + description = 'Get the flag to the enemy end zone.' + game_settings = [ + ('Score to Win', { + 'min_value': 7, + 'default': 21, + 'increment': 7 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ] @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: # We only support two-team play. return issubclass(sessiontype, ba.DualTeamSession) - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Get the flag to the enemy end zone.' - @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('football') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Score to Win', { - 'min_value': 7, - 'default': 21, - 'increment': 7 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }) - ] # yapf: disable - def __init__(self, settings: Dict[str, Any]): super().__init__(settings) self._scoreboard: Optional[Scoreboard] = Scoreboard() @@ -131,7 +120,6 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]): self._score_sound = ba.getsound('score') self._swipsound = ba.getsound('swip') self._whistle_sound = ba.getsound('refWhistle') - self.score_region_material = ba.Material() self.score_region_material.add_actions( conditions=('they_have_material', @@ -147,6 +135,7 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]): def get_instance_description(self) -> Union[str, Sequence]: 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 .. @@ -155,7 +144,7 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]): return 'Score ${ARG1} touchdowns.', touchdowns return 'Score a touchdown.' - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: touchdowns = self.settings_raw['Score to Win'] / 7 touchdowns = math.ceil(touchdowns) if touchdowns > 1: @@ -336,15 +325,9 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]): Co-op variant of football """ + name = 'Football' tips = ['Use the pick-up button to grab the flag < ${PICKUP} >'] - - @classmethod - def get_name(cls) -> str: - return 'Football' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(scoretype=ba.ScoreType.MILLISECONDS, version='B') + score_info = ba.ScoreInfo(scoretype=ba.ScoreType.MILLISECONDS, version='B') # FIXME: Need to update co-op games to use get_score_info. def get_score_type(self) -> str: @@ -357,7 +340,7 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]): return 'Score ${ARG1} touchdowns.', touchdowns return 'Score a touchdown.' - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: touchdowns = self._score_to_win / 7 touchdowns = math.ceil(touchdowns) if touchdowns > 1: diff --git a/assets/src/ba_data/python/bastd/game/hockey.py b/assets/src/ba_data/python/bastd/game/hockey.py index fa611c6b..de4a813a 100644 --- a/assets/src/ba_data/python/bastd/game/hockey.py +++ b/assets/src/ba_data/python/bastd/game/hockey.py @@ -31,8 +31,7 @@ import ba from bastd.actor import playerspaz if TYPE_CHECKING: - from typing import (Any, Sequence, Dict, Type, List, Tuple, Optional, - Union) + from typing import Any, Sequence, Dict, Type, List, Optional, Union class PuckDeathMessage: @@ -109,13 +108,26 @@ class Puck(ba.Actor): class HockeyGame(ba.TeamGameActivity[ba.Player, ba.Team]): """Ice hockey game.""" - @classmethod - def get_name(cls) -> str: - return 'Hockey' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Score some goals.' + name = 'Hockey' + description = 'Score some goals.' + game_settings = [ + ('Score to Win', { + 'min_value': 1, + 'default': 1, + 'increment': 1 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ] @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -125,26 +137,6 @@ class HockeyGame(ba.TeamGameActivity[ba.Player, ba.Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('hockey') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Score to Win', { - 'min_value': 1, 'default': 1, 'increment': 1 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), - ('2 Minutes', 120), ('5 Minutes', 300), - ('10 Minutes', 600), ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - })] # yapf: disable - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard from bastd.actor import powerupbox @@ -201,7 +193,7 @@ class HockeyGame(ba.TeamGameActivity[ba.Player, ba.Team]): return 'Score a goal.' return 'Score ${ARG1} goals.', self.settings_raw['Score to Win'] - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: if self.settings_raw['Score to Win'] == 1: return 'score a goal' return 'score ${ARG1} goals', self.settings_raw['Score to Win'] diff --git a/assets/src/ba_data/python/bastd/game/keepaway.py b/assets/src/ba_data/python/bastd/game/keepaway.py index 117cd5bb..b3ea1d54 100644 --- a/assets/src/ba_data/python/bastd/game/keepaway.py +++ b/assets/src/ba_data/python/bastd/game/keepaway.py @@ -25,7 +25,7 @@ from __future__ import annotations -from dataclasses import dataclass +from enum import Enum from typing import TYPE_CHECKING import ba @@ -34,16 +34,21 @@ from bastd.actor.flag import (Flag, FlagDroppedMessage, FlagDeathMessage, from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage if TYPE_CHECKING: - from typing import (Any, Type, List, Tuple, Dict, Optional, Sequence, - Union) + from typing import Any, Type, List, Dict, Optional, Sequence, Union + + +class FlagState(Enum): + """States our single flag can be in.""" + NEW = 0 + UNCONTESTED = 1 + CONTESTED = 2 + HELD = 3 -@dataclass(eq=False) class Player(ba.Player['Team']): """Our player type for this game.""" -@dataclass(eq=False) class Team(ba.Team[Player]): """Our team type for this game.""" @@ -52,22 +57,27 @@ class Team(ba.Team[Player]): class KeepAwayGame(ba.TeamGameActivity[Player, Team]): """Game where you try to keep the flag away from your enemies.""" - FLAG_NEW = 0 - FLAG_UNCONTESTED = 1 - FLAG_CONTESTED = 2 - FLAG_HELD = 3 - - @classmethod - def get_name(cls) -> str: - return 'Keep Away' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Carry the flag for a set length of time.' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Time Held') + name = 'Keep Away' + description = 'Carry the flag for a set length of time.' + game_settings = [ + ('Hold Time', { + 'min_value': 10, + 'default': 30, + 'increment': 10 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ] + score_info = ba.ScoreInfo(label='Time Held') @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -78,29 +88,6 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('keep_away') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Hold Time', { - 'min_value': 10, - 'default': 30, - 'increment': 10 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }) - ] # yapf: disable - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) @@ -122,7 +109,7 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): self._flag_spawn_pos: Optional[Sequence[float]] = None self._update_timer: Optional[ba.Timer] = None self._holding_players: List[Player] = [] - self._flag_state: Optional[int] = None + self._flag_state: Optional[FlagState] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[Team] = None self._flag: Optional[Flag] = None @@ -131,7 +118,7 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): return ('Carry the flag for ${ARG1} seconds.', self.settings_raw['Hold Time']) - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: return ('carry the flag for ${ARG1} seconds', self.settings_raw['Hold Time']) @@ -224,18 +211,18 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): assert self._flag_light assert self._flag.node if len(holding_teams) > 1: - self._flag_state = self.FLAG_CONTESTED + self._flag_state = FlagState.CONTESTED self._scoring_team = None self._flag_light.color = (0.6, 0.6, 0.1) self._flag.node.color = (1.0, 1.0, 0.4) elif len(holding_teams) == 1: holding_team = list(holding_teams)[0] - self._flag_state = self.FLAG_HELD + self._flag_state = FlagState.HELD self._scoring_team = holding_team self._flag_light.color = ba.normalized_color(holding_team.color) self._flag.node.color = holding_team.color else: - self._flag_state = self.FLAG_UNCONTESTED + self._flag_state = FlagState.UNCONTESTED self._scoring_team = None self._flag_light.color = (0.2, 0.2, 0.2) self._flag.node.color = (1, 1, 1) @@ -248,7 +235,7 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): self._flash_flag_spawn() assert self._flag_spawn_pos is not None self._flag = Flag(dropped_timeout=20, position=self._flag_spawn_pos) - self._flag_state = self.FLAG_NEW + self._flag_state = FlagState.NEW self._flag_light = ba.newnode('light', owner=self._flag.node, attrs={ diff --git a/assets/src/ba_data/python/bastd/game/kingofthehill.py b/assets/src/ba_data/python/bastd/game/kingofthehill.py index d01f8e3b..b69be0f4 100644 --- a/assets/src/ba_data/python/bastd/game/kingofthehill.py +++ b/assets/src/ba_data/python/bastd/game/kingofthehill.py @@ -26,51 +26,66 @@ from __future__ import annotations import weakref -from dataclasses import dataclass +from enum import Enum from typing import TYPE_CHECKING import ba from bastd.actor.flag import Flag from bastd.actor.playerspaz import PlayerSpaz, PlayerSpazDeathMessage +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from weakref import ReferenceType - from typing import (Any, Type, List, Dict, Tuple, Optional, Sequence, - Union) + from typing import Any, Type, List, Dict, Optional, Sequence, Union + + +class FlagState(Enum): + """States our single flag can be in.""" + NEW = 0 + UNCONTESTED = 1 + CONTESTED = 2 + HELD = 3 -@dataclass(eq=False) class Player(ba.Player['Team']): """Our player type for this game.""" - time_at_flag: int = 0 + + def __init__(self) -> None: + self.time_at_flag = 0 -@dataclass(eq=False) class Team(ba.Team[Player]): """Our team type for this game.""" - time_remaining: int + + def __init__(self, time_remaining: int) -> None: + self.time_remaining = time_remaining # ba_meta export game class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): """Game where a team wins by holding a 'hill' for a set amount of time.""" - FLAG_NEW = 0 - FLAG_UNCONTESTED = 1 - FLAG_CONTESTED = 2 - FLAG_HELD = 3 - - @classmethod - def get_name(cls) -> str: - return 'King of the Hill' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Secure the flag for a set length of time.' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Time Held') + name = 'King of the Hill' + description = 'Secure the flag for a set length of time.' + game_settings = [ + ('Hold Time', { + 'min_value': 10, + 'default': 30, + 'increment': 10 + }), + ('Time Limit', { + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], + 'default': 0 + }), + ('Respawn Times', { + 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), + ('Long', 2.0), ('Longer', 4.0)], + 'default': 1.0 + }), + ] + score_info = ba.ScoreInfo(label='Time Held') @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -80,31 +95,7 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ba.getmaps('king_of_the_hill') - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Hold Time', { - 'min_value': 10, - 'default': 30, - 'increment': 10 - }), - ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), - ('5 Minutes', 300), ('10 Minutes', 600), - ('20 Minutes', 1200)], - 'default': 0 - }), - ('Respawn Times', { - 'choices': [('Shorter', 0.25), ('Short', 0.5), ('Normal', 1.0), - ('Long', 2.0), ('Longer', 4.0)], - 'default': 1.0 - }), - ] - def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') @@ -122,23 +113,23 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): 1: ba.getsound('announceOne') } self._flag_pos: Optional[Sequence[float]] = None - self._flag_state: Optional[int] = None + self._flag_state: Optional[FlagState] = None self._flag: Optional[Flag] = None self._flag_light: Optional[ba.Node] = None self._scoring_team: Optional[ReferenceType[Team]] = None self._hold_time = int(settings['Hold Time']) self._time_limit = float(settings['Time Limit']) - self._flag_region_material = ba.Material() self._flag_region_material.add_actions( conditions=('they_have_material', ba.sharedobj('player_material')), - actions=(('modify_part_collision', 'collide', - True), ('modify_part_collision', 'physical', False), - ('call', 'at_connect', - ba.Call(self._handle_player_flag_region_collide, True)), - ('call', 'at_disconnect', - ba.Call(self._handle_player_flag_region_collide, - False)))) + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', False), + ('call', 'at_connect', + ba.Call(self._handle_player_flag_region_collide, True)), + ('call', 'at_disconnect', + ba.Call(self._handle_player_flag_region_collide, False)), + )) # Base class overrides. self.default_music = ba.MusicType.SCARY @@ -146,7 +137,7 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): def get_instance_description(self) -> Union[str, Sequence]: return 'Secure the flag for ${ARG1} seconds.', self._hold_time - def get_instance_scoreboard_description(self) -> Union[str, Sequence]: + def get_instance_description_short(self) -> Union[str, Sequence]: return 'secure the flag for ${ARG1} seconds', self._hold_time def create_team(self, sessionteam: ba.SessionTeam) -> Team: @@ -158,7 +149,7 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): self.setup_standard_powerup_drops() self._flag_pos = self.map.get_flag_position(None) ba.timer(1.0, self._tick, repeat=True) - self._flag_state = self.FLAG_NEW + self._flag_state = FlagState.NEW self.project_flag_stand(self._flag_pos) self._flag = Flag(position=self._flag_pos, @@ -172,7 +163,6 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): 'radius': 0.4, 'color': (0.2, 0.2, 0.2) }) - # Flag region. flagmats = [ self._flag_region_material, @@ -238,18 +228,18 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): assert self._flag is not None assert self._flag.node if len(holding_teams) > 1: - self._flag_state = self.FLAG_CONTESTED + self._flag_state = FlagState.CONTESTED self._scoring_team = None self._flag_light.color = (0.6, 0.6, 0.1) self._flag.node.color = (1.0, 1.0, 0.4) elif len(holding_teams) == 1: holding_team = list(holding_teams)[0] - self._flag_state = self.FLAG_HELD + self._flag_state = FlagState.HELD self._scoring_team = weakref.ref(holding_team) self._flag_light.color = ba.normalized_color(holding_team.color) self._flag.node.color = holding_team.color else: - self._flag_state = self.FLAG_UNCONTESTED + self._flag_state = FlagState.UNCONTESTED self._scoring_team = None self._flag_light.color = (0.2, 0.2, 0.2) self._flag.node.color = (1, 1, 1) diff --git a/assets/src/ba_data/python/bastd/game/meteorshower.py b/assets/src/ba_data/python/bastd/game/meteorshower.py index 8b5853ea..3e1103dd 100644 --- a/assets/src/ba_data/python/bastd/game/meteorshower.py +++ b/assets/src/ba_data/python/bastd/game/meteorshower.py @@ -34,7 +34,7 @@ from bastd.actor.playerspaz import PlayerSpazDeathMessage from bastd.actor.onscreentimer import OnScreenTimer if TYPE_CHECKING: - from typing import Any, Tuple, Sequence, Optional, List, Dict, Type, Type + from typing import Any, Sequence, Optional, List, Dict, Type, Type class Player(ba.Player['Team']): @@ -53,31 +53,21 @@ class Team(ba.Team[Player]): class MeteorShowerGame(ba.TeamGameActivity[Player, Team]): """Minigame involving dodging falling bombs.""" - @classmethod - def get_name(cls) -> str: - return 'Meteor Shower' + name = 'Meteor Shower' + description = 'Dodge the falling bombs.' + game_settings = [('Epic Mode', {'default': False})] + score_info = ba.ScoreInfo(label='Survived', + scoretype=ba.ScoreType.MILLISECONDS, + version='B') - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Survived', - scoretype=ba.ScoreType.MILLISECONDS, - version='B') - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Dodge the falling bombs.' + # Print messages when players die (since its meaningful in this game). + announce_player_deaths = True # we're currently hard-coded for one map.. @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: return ['Rampage'] - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [('Epic Mode', {'default': False})] - # We support teams, free-for-all, and co-op sessions. @classmethod def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: @@ -85,9 +75,6 @@ class MeteorShowerGame(ba.TeamGameActivity[Player, Team]): or issubclass(sessiontype, ba.FreeForAllSession) or issubclass(sessiontype, ba.CoopSession)) - # Print messages when players die (since its meaningful in this game). - announce_player_deaths = True - def __init__(self, settings: Dict[str, Any]): super().__init__(settings) @@ -256,9 +243,6 @@ class MeteorShowerGame(ba.TeamGameActivity[Player, Team]): for team in self.teams: for player in team.players: - if not player: - print(f'GOT DEAD PLAYER {id(player)}') - survived = False # Throw an extra fudge factor in so teams that diff --git a/assets/src/ba_data/python/bastd/game/ninjafight.py b/assets/src/ba_data/python/bastd/game/ninjafight.py index 04c44ef2..85a71656 100644 --- a/assets/src/ba_data/python/bastd/game/ninjafight.py +++ b/assets/src/ba_data/python/bastd/game/ninjafight.py @@ -44,19 +44,11 @@ class NinjaFightGame(ba.TeamGameActivity[ba.Player, ba.Team]): of Ninjas as fast as possible """ - @classmethod - def get_name(cls) -> str: - return 'Ninja Fight' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Time', - scoretype=ba.ScoreType.MILLISECONDS, - lower_is_better=True) - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'How fast can you defeat the ninjas?' + name = 'Ninja Fight' + description = 'How fast can you defeat the ninjas?' + score_info = ba.ScoreInfo(label='Time', + scoretype=ba.ScoreType.MILLISECONDS, + lower_is_better=True) @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: diff --git a/assets/src/ba_data/python/bastd/game/onslaught.py b/assets/src/ba_data/python/bastd/game/onslaught.py index c9df8d80..225b4773 100644 --- a/assets/src/ba_data/python/bastd/game/onslaught.py +++ b/assets/src/ba_data/python/bastd/game/onslaught.py @@ -52,6 +52,9 @@ class Team(ba.Team[Player]): class OnslaughtGame(ba.CoopGameActivity[Player, Team]): """Co-op game where players try to survive attacking waves of enemies.""" + name = 'Onslaught' + description = 'Defeat all enemies.' + tips: List[Union[str, Dict[str, Any]]] = [ 'Hold any button to run.' ' (Trigger buttons work well if you have them)', @@ -63,13 +66,8 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): 'Your punches do much more damage if you are running or spinning.' ] - @classmethod - def get_name(cls) -> str: - return 'Onslaught' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Defeat all enemies.' + # Show messages when players die since it matters here. + announce_player_deaths = True def __init__(self, settings: Dict[str, Any]): @@ -88,9 +86,6 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): super().__init__(settings) - # Show messages when players die since it matters here. - self.announce_player_deaths = True - self._new_wave_sound = ba.getsound('scoreHit01') self._winsound = ba.getsound('score') self._cashregistersound = ba.getsound('cashRegister') diff --git a/assets/src/ba_data/python/bastd/game/race.py b/assets/src/ba_data/python/bastd/game/race.py index 60b80066..d55054b9 100644 --- a/assets/src/ba_data/python/bastd/game/race.py +++ b/assets/src/ba_data/python/bastd/game/race.py @@ -81,30 +81,14 @@ class Team(ba.Team[Player]): class RaceGame(ba.TeamGameActivity[Player, Team]): """Game of racing around a track.""" - @classmethod - def get_name(cls) -> str: - return 'Race' + name = 'Race' + description = 'Run real fast!' + score_info = ba.ScoreInfo(label='Time', + lower_is_better=True, + scoretype=ba.ScoreType.MILLISECONDS) @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Run real fast!' - - @classmethod - def get_score_info(cls) -> ba.ScoreInfo: - return ba.ScoreInfo(label='Time', - lower_is_better=True, - scoretype=ba.ScoreType.MILLISECONDS) - - @classmethod - def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: - return issubclass(sessiontype, ba.MultiTeamSession) - - @classmethod - def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: - return ba.getmaps('race') - - @classmethod - def get_settings( + def get_game_settings( cls, sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: settings: List[Tuple[str, Dict[str, Any]]] = [ @@ -114,9 +98,9 @@ class RaceGame(ba.TeamGameActivity[Player, Team]): 'increment': 1 }), ('Time Limit', { - 'choices': [('None', 0), ('1 Minute', 60), - ('2 Minutes', 120), ('5 Minutes', 300), - ('10 Minutes', 600), ('20 Minutes', 1200)], + 'choices': [('None', 0), ('1 Minute', 60), ('2 Minutes', 120), + ('5 Minutes', 300), ('10 Minutes', 600), + ('20 Minutes', 1200)], 'default': 0 }), ('Mine Spawning', { @@ -128,16 +112,26 @@ class RaceGame(ba.TeamGameActivity[Player, Team]): 'choices': [('None', 0), ('8 Seconds', 8000), ('4 Seconds', 4000), ('2 Seconds', 2000), ('1 Second', 1000)], - 'default': 2000 + 'default': 2000 }), ('Epic Mode', { 'default': False - })] # yapf: disable + }), + ] + # We have some specific settings in teams mode. if issubclass(sessiontype, ba.DualTeamSession): settings.append(('Entire Team Must Finish', {'default': False})) return settings + @classmethod + def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool: + return issubclass(sessiontype, ba.MultiTeamSession) + + @classmethod + def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: + return ba.getmaps('race') + def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard self._race_started = False @@ -175,7 +169,7 @@ class RaceGame(ba.TeamGameActivity[Player, Team]): 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]: + def get_instance_description_short(self) -> Union[str, Sequence]: if self.settings_raw['Laps'] > 1: return 'run ${ARG1} laps', self.settings_raw['Laps'] return 'run 1 lap' diff --git a/assets/src/ba_data/python/bastd/game/runaround.py b/assets/src/ba_data/python/bastd/game/runaround.py index 302494a2..8e7d360f 100644 --- a/assets/src/ba_data/python/bastd/game/runaround.py +++ b/assets/src/ba_data/python/bastd/game/runaround.py @@ -41,6 +41,8 @@ if TYPE_CHECKING: class RunaroundGame(ba.CoopGameActivity[ba.Player, ba.Team]): """Game involving trying to bomb bots as they walk through the map.""" + name = 'Runaround' + description = 'Prevent enemies from reaching the exit.' tips = [ 'Jump just as you\'re throwing to get bombs up to the highest levels.', 'No, you can\'t get up on the ledge. You have to throw bombs.', @@ -64,14 +66,6 @@ class RunaroundGame(ba.CoopGameActivity[ba.Player, ba.Team]): spazbot.StickyBot: 0.5 } - @classmethod - def get_name(cls) -> str: - return 'Runaround' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Prevent enemies from reaching the exit.' - def __init__(self, settings: Dict[str, Any]): settings['map'] = 'Tower D' super().__init__(settings) diff --git a/assets/src/ba_data/python/bastd/game/targetpractice.py b/assets/src/ba_data/python/bastd/game/targetpractice.py index 3c18deb4..9ff37d9b 100644 --- a/assets/src/ba_data/python/bastd/game/targetpractice.py +++ b/assets/src/ba_data/python/bastd/game/targetpractice.py @@ -26,41 +26,49 @@ from __future__ import annotations import random -from dataclasses import dataclass from typing import TYPE_CHECKING import ba from bastd.actor import playerspaz if TYPE_CHECKING: - from typing import Any, Type, List, Dict, Optional, Tuple, Sequence + from typing import Any, Type, List, Dict, Optional, Sequence from bastd.actor.onscreencountdown import OnScreenCountdown from bastd.actor.bomb import Bomb, Blast -@dataclass(eq=False) class Player(ba.Player['Team']): """Our player type for this game.""" - streak: int = 0 + + def __init__(self) -> None: + self.streak = 0 -@dataclass(eq=False) class Team(ba.Team[Player]): """Our team type for this game.""" - score: int = 0 + + def __init__(self) -> None: + self.score = 0 # ba_meta export game class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): """Game where players try to hit targets with bombs.""" - @classmethod - def get_name(cls) -> str: - return 'Target Practice' - - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Bomb as many targets as you can.' + name = 'Target Practice' + description = 'Bomb as many targets as you can.' + game_settings = [ + ('Target Count', { + 'min_value': 1, + 'default': 3 + }), + ('Enable Impact Bombs', { + 'default': True + }), + ('Enable Triple Bombs', { + 'default': True + }), + ] @classmethod def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]: @@ -72,23 +80,6 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): return (issubclass(sessiontype, ba.CoopSession) or issubclass(sessiontype, ba.MultiTeamSession)) - @classmethod - def get_settings( - cls, - sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]: - return [ - ('Target Count', { - 'min_value': 1, - 'default': 3 - }), - ('Enable Impact Bombs', { - 'default': True - }), - ('Enable Triple Bombs', { - 'default': True - }), - ] - def __init__(self, settings: Dict[str, Any]): from bastd.actor.scoreboard import Scoreboard super().__init__(settings) diff --git a/assets/src/ba_data/python/bastd/game/thelaststand.py b/assets/src/ba_data/python/bastd/game/thelaststand.py index cff0e3c4..dafea99b 100644 --- a/assets/src/ba_data/python/bastd/game/thelaststand.py +++ b/assets/src/ba_data/python/bastd/game/thelaststand.py @@ -49,29 +49,22 @@ class Team(ba.Team[Player]): class TheLastStandGame(ba.CoopGameActivity[Player, Team]): """Slow motion how-long-can-you-last game.""" + name = 'The Last Stand' + description = 'Final glorious epic slow motion battle to the death.' tips = [ 'This level never ends, but a high score here\n' 'will earn you eternal respect throughout the world.' ] - @classmethod - def get_name(cls) -> str: - return 'The Last Stand' + # Show messages when players die since it matters here. + announce_player_deaths = True - @classmethod - def get_description(cls, sessiontype: Type[ba.Session]) -> str: - return 'Final glorious epic slow motion battle to the death.' + # And of course the most important part. + slow_motion = True def __init__(self, settings: Dict[str, Any]): settings['map'] = 'Rampage' super().__init__(settings) - - # Show messages when players die since it matters here. - self.announce_player_deaths = True - - # And of course the most important part. - self.slow_motion = True - self._new_wave_sound = ba.getsound('scoreHit01') self._winsound = ba.getsound('score') self._cashregistersound = ba.getsound('cashRegister') diff --git a/assets/src/ba_data/python/bastd/ui/playlist/editgame.py b/assets/src/ba_data/python/bastd/ui/playlist/editgame.py index 60fc3aa0..3912bfe3 100644 --- a/assets/src/ba_data/python/bastd/ui/playlist/editgame.py +++ b/assets/src/ba_data/python/bastd/ui/playlist/editgame.py @@ -72,7 +72,7 @@ class PlaylistEditGameWindow(ba.Window): ba.screenmessage(ba.Lstr(resource='noValidMapsErrorText')) raise Exception('No valid maps') - self._settings_defs = gameclass.get_settings(sessiontype) + self._settings_defs = gameclass.get_game_settings(sessiontype) self._completion_call = completion_call # To start with, pick a random map out of the ones we own. diff --git a/docs/ba_module.md b/docs/ba_module.md index d041935b..17580518 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -

last updated on 2020-05-19 for Ballistica version 1.5.0 build 20021

+

last updated on 2020-05-19 for Ballistica version 1.5.0 build 20023

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 let me know. Happy modding!


@@ -1519,7 +1519,7 @@ start_long_action(callback_when_done=ba.ContextC

Methods Inherited:

-
add_actor_weak_ref(), add_player(), add_team(), begin(), continue_or_end_game(), create_config_ui(), create_player(), create_team(), dep_is_present(), destroy(), end(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_dynamic_deps(), get_instance_description(), get_instance_display_string(), get_instance_scoreboard_description(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_settings(), get_supported_maps(), get_team_display_string(), handlemessage(), has_begun(), has_ended(), has_transitioned_in(), is_transitioning_out(), is_waiting_for_continue(), on_continue(), on_expire(), on_player_join(), on_player_leave(), on_team_join(), on_team_leave(), on_transition_in(), on_transition_out(), project_flag_stand(), remove_player(), remove_team(), respawn_player(), retain_actor(), set_has_ended(), set_immediate_end(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), transition_in(), transition_out()
+
add_actor_weak_ref(), add_player(), add_team(), begin(), continue_or_end_game(), create_config_ui(), create_player(), create_team(), dep_is_present(), destroy(), end(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_dynamic_deps(), get_game_settings(), get_instance_description(), get_instance_description_short(), get_instance_display_string(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_supported_maps(), get_team_display_string(), handlemessage(), has_begun(), has_ended(), has_transitioned_in(), is_transitioning_out(), is_waiting_for_continue(), on_continue(), on_expire(), on_player_join(), on_player_leave(), on_team_join(), on_team_leave(), on_transition_in(), on_transition_out(), project_flag_stand(), remove_player(), remove_team(), respawn_player(), retain_actor(), set_has_ended(), set_immediate_end(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), transition_in(), transition_out()

Methods Defined or Overridden:

<constructor>, celebrate(), fade_to_red(), get_score_type(), on_begin(), setup_low_life_warning_sound(), spawn_player_spaz(), supports_session_type()
@@ -2043,7 +2043,7 @@ its time with lingering corpses, sound effects, etc.

Methods Inherited:

add_actor_weak_ref(), add_player(), add_team(), begin(), create_player(), create_team(), dep_is_present(), destroy(), get_dynamic_deps(), has_begun(), has_ended(), has_transitioned_in(), is_transitioning_out(), on_expire(), on_team_join(), on_team_leave(), on_transition_out(), remove_player(), remove_team(), retain_actor(), set_has_ended(), set_immediate_end(), transition_in(), transition_out()

Methods Defined or Overridden:

-
<constructor>, continue_or_end_game(), create_config_ui(), end(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_instance_description(), get_instance_display_string(), get_instance_scoreboard_description(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_settings(), get_supported_maps(), get_team_display_string(), handlemessage(), is_waiting_for_continue(), on_begin(), on_continue(), on_player_join(), on_player_leave(), on_transition_in(), project_flag_stand(), respawn_player(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), spawn_player_spaz(), supports_session_type()
+
<constructor>, continue_or_end_game(), create_config_ui(), end(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_game_settings(), get_instance_description(), get_instance_description_short(), get_instance_display_string(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_supported_maps(), get_team_display_string(), handlemessage(), is_waiting_for_continue(), on_begin(), on_continue(), on_player_join(), on_player_leave(), on_transition_in(), project_flag_stand(), respawn_player(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), spawn_player_spaz(), supports_session_type()

<constructor>

ba.GameActivity(settings: Dict[str, Any])

@@ -2073,9 +2073,9 @@ and calls either end_game or continue_game depending on the result

success or None on cancel.

Generally subclasses don't need to override this; if they override -ba.GameActivity.get_settings() and ba.GameActivity.get_supported_maps() -they can just rely on the default implementation here which calls those -methods.

+ba.GameActivity.get_game_settings() and +ba.GameActivity.get_supported_maps() they can just rely on +the default implementation here which calls those methods.

end()

@@ -2114,9 +2114,11 @@ is up next in a series.

<class method>

get_description(sessiontype: Type[ba.Session]) -> str

-

Subclasses should override this to return a description for this -activity type (in English) within the context of the given -ba.Session type.

+

Get a str description of this game type.

+ +

The default implementation simply returns the 'description' class var. +Classes which want to change their description depending on the session +can override this method.

get_description_display_string()

@@ -2137,92 +2139,9 @@ activity type (in English) within the context of the given

Subclasses should override get_name(); not this.

-

get_instance_description()

-

get_instance_description(self) -> Union[str, Sequence]

- -

Return a description for this game instance, in English.

- -

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

- -

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

- -
# this will give us something like 'Score 3 goals.' in English
-# and can properly translate to 'Anota 3 goles.' in Spanish.
-# If we just returned the string 'Score 3 Goals' here, there would
-# have to be a translation entry for each specific number. ew.
-return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]
- -

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

- -
-

get_instance_display_string()

-

get_instance_display_string(self) -> ba.Lstr

- -

Return a name for this particular game instance.

- -
-

get_instance_scoreboard_description()

-

get_instance_scoreboard_description(self) -> Union[str, Sequence]

- -

Return a short description for this game instance in English.

- -

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

- -

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

- -
# this will give us something like 'score 3 goals' in English
-# and can properly translate to 'anota 3 goles' in Spanish.
-# If we just returned the string 'score 3 goals' here, there would
-# have to be a translation entry for each specific number. ew.
-return ['score ${ARG1} goals', self.settings_raw['Score to Win']]
- -

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

- -
-

get_instance_scoreboard_display_string()

-

get_instance_scoreboard_display_string(self) -> ba.Lstr

- -

Return a name for this particular game instance.

- -

This name is used above the game scoreboard in the corner -of the screen, so it should be as concise as possible.

- -
-

get_name()

+

get_game_settings()

<class method>
-

get_name() -> str

- -

Return a str name for this game type.

- -
-

get_score_info()

-
<class method>
-

get_score_info() -> ba.ScoreInfo

- -

Return info about game scoring setup; can be overridden by games.

- -
-

get_settings()

-
<class method>
-

get_settings(sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]

+

get_game_settings(sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]

Called by the default ba.GameActivity.create_config_ui() implementation; should return a dict of config options to be presented @@ -2244,9 +2163,9 @@ of a name and a dict of options.

'increment': Value increment for int/float settings.

-
# example get_settings() implementation for a capture-the-flag game:
+
# example get_game_settings() for a capture-the-flag game:
 @classmethod
-def get_settings(cls,sessiontype):
+def get_game_settings(cls, sessiontype):
     return [("Score to Win", {
                 'default': 3,
                 'min_value': 1
@@ -2280,6 +2199,91 @@ def get_settings(cls,sessiontype):
                 'default': False
             })]
+
+

get_instance_description()

+

get_instance_description(self) -> Union[str, Sequence]

+ +

Return a description for this game instance, in English.

+ +

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

+ +

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

+ +
# This will give us something like 'Score 3 goals.' in English
+# and can properly translate to 'Anota 3 goles.' in Spanish.
+# If we just returned the string 'Score 3 Goals' here, there would
+# have to be a translation entry for each specific number. ew.
+return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]
+ +

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

+ +
+

get_instance_description_short()

+

get_instance_description_short(self) -> Union[str, Sequence]

+ +

Return a short description for this game instance in English.

+ +

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

+ +

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

+ +
# This will give us something like 'score 3 goals' in English
+# and can properly translate to 'anota 3 goles' in Spanish.
+# If we just returned the string 'score 3 goals' here, there would
+# have to be a translation entry for each specific number. ew.
+return ['score ${ARG1} goals', self.settings_raw['Score to Win']]
+ +

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

+ +
+

get_instance_display_string()

+

get_instance_display_string(self) -> ba.Lstr

+ +

Return a name for this particular game instance.

+ +
+

get_instance_scoreboard_display_string()

+

get_instance_scoreboard_display_string(self) -> ba.Lstr

+ +

Return a name for this particular game instance.

+ +

This name is used above the game scoreboard in the corner +of the screen, so it should be as concise as possible.

+ +
+

get_name()

+
<class method>
+

get_name() -> str

+ +

Return a str name for this game type.

+ +

This default implementation simply returns the 'name' class attr.

+ +
+

get_score_info()

+
<class method>
+

get_score_info() -> ba.ScoreInfo

+ +

Return info about game scoring setup; can be overridden by games.

+

get_supported_maps()

<class method>
@@ -4810,7 +4814,7 @@ of the session.

Methods Inherited:

-
add_actor_weak_ref(), add_player(), add_team(), begin(), continue_or_end_game(), create_config_ui(), create_player(), create_team(), dep_is_present(), destroy(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_dynamic_deps(), get_instance_description(), get_instance_display_string(), get_instance_scoreboard_description(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_settings(), get_supported_maps(), get_team_display_string(), handlemessage(), has_begun(), has_ended(), has_transitioned_in(), is_transitioning_out(), is_waiting_for_continue(), on_continue(), on_expire(), on_player_join(), on_player_leave(), on_team_join(), on_team_leave(), on_transition_out(), project_flag_stand(), remove_player(), remove_team(), respawn_player(), retain_actor(), set_has_ended(), set_immediate_end(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), transition_in(), transition_out()
+
add_actor_weak_ref(), add_player(), add_team(), begin(), continue_or_end_game(), create_config_ui(), create_player(), create_team(), dep_is_present(), destroy(), end_game(), get_config_display_string(), get_description(), get_description_display_string(), get_display_string(), get_dynamic_deps(), get_game_settings(), get_instance_description(), get_instance_description_short(), get_instance_display_string(), get_instance_scoreboard_display_string(), get_name(), get_score_info(), get_supported_maps(), get_team_display_string(), handlemessage(), has_begun(), has_ended(), has_transitioned_in(), is_transitioning_out(), is_waiting_for_continue(), on_continue(), on_expire(), on_player_join(), on_player_leave(), on_team_join(), on_team_leave(), on_transition_out(), project_flag_stand(), remove_player(), remove_team(), respawn_player(), retain_actor(), set_has_ended(), set_immediate_end(), setup_standard_powerup_drops(), setup_standard_time_limit(), show_info(), show_scoreboard_info(), show_zoom_message(), spawn_player(), spawn_player_if_exists(), transition_in(), transition_out()

Methods Defined or Overridden:

<constructor>, end(), on_begin(), on_transition_in(), spawn_player_spaz(), supports_session_type()