mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-29 10:43:21 +08:00
Added shorthand ways to define some game attrs
This commit is contained in:
parent
5828881f3d
commit
3ff115272f
@ -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']
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -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={
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]:
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2020-05-19 for Ballistica version 1.5.0 build 20021</em></h4>
|
||||
<h4><em>last updated on 2020-05-19 for Ballistica version 1.5.0 build 20023</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
@ -1519,7 +1519,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_CoopGameActivity____init__"><constructor></a>, <a href="#method_ba_CoopGameActivity__celebrate">celebrate()</a>, <a href="#method_ba_CoopGameActivity__fade_to_red">fade_to_red()</a>, <a href="#method_ba_CoopGameActivity__get_score_type">get_score_type()</a>, <a href="#method_ba_CoopGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_CoopGameActivity__setup_low_life_warning_sound">setup_low_life_warning_sound()</a>, <a href="#method_ba_CoopGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_CoopGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
@ -2043,7 +2043,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_Activity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_Activity__add_player">add_player()</a>, <a href="#method_ba_Activity__add_team">add_team()</a>, <a href="#method_ba_Activity__begin">begin()</a>, <a href="#method_ba_Activity__create_player">create_player()</a>, <a href="#method_ba_Activity__create_team">create_team()</a>, <a href="#method_ba_Activity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_Activity__destroy">destroy()</a>, <a href="#method_ba_Activity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_Activity__has_begun">has_begun()</a>, <a href="#method_ba_Activity__has_ended">has_ended()</a>, <a href="#method_ba_Activity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_Activity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_Activity__on_expire">on_expire()</a>, <a href="#method_ba_Activity__on_team_join">on_team_join()</a>, <a href="#method_ba_Activity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_Activity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_Activity__remove_player">remove_player()</a>, <a href="#method_ba_Activity__remove_team">remove_team()</a>, <a href="#method_ba_Activity__retain_actor">retain_actor()</a>, <a href="#method_ba_Activity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_Activity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_Activity__transition_in">transition_in()</a>, <a href="#method_ba_Activity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_GameActivity____init__"><constructor></a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_begin">on_begin()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_GameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<h5><a href="#method_ba_GameActivity____init__"><constructor></a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__end">end()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_begin">on_begin()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_GameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
<dt><h4><a name="method_ba_GameActivity____init__"><constructor></a></dt></h4><dd>
|
||||
<p><span>ba.GameActivity(settings: Dict[str, Any])</span></p>
|
||||
@ -2073,9 +2073,9 @@ and calls either end_game or continue_game depending on the result</p>
|
||||
success or None on cancel.</p>
|
||||
|
||||
<p>Generally subclasses don't need to override this; if they override
|
||||
<a href="#method_ba_GameActivity__get_settings">ba.GameActivity.get_settings</a>() and <a href="#method_ba_GameActivity__get_supported_maps">ba.GameActivity.get_supported_maps</a>()
|
||||
they can just rely on the default implementation here which calls those
|
||||
methods.</p>
|
||||
<a href="#method_ba_GameActivity__get_game_settings">ba.GameActivity.get_game_settings</a>() and
|
||||
<a href="#method_ba_GameActivity__get_supported_maps">ba.GameActivity.get_supported_maps</a>() they can just rely on
|
||||
the default implementation here which calls those methods.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__end">end()</a></dt></h4><dd>
|
||||
@ -2114,9 +2114,11 @@ is up next in a series.</p>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_description(sessiontype: Type[<a href="#class_ba_Session">ba.Session</a>]) -> str </span></p>
|
||||
|
||||
<p>Subclasses should override this to return a description for this
|
||||
activity type (in English) within the context of the given
|
||||
<a href="#class_ba_Session">ba.Session</a> type.</p>
|
||||
<p>Get a str description of this game type.</p>
|
||||
|
||||
<p>The default implementation simply returns the 'description' class var.
|
||||
Classes which want to change their description depending on the session
|
||||
can override this method.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_description_display_string">get_description_display_string()</a></dt></h4><dd>
|
||||
@ -2137,92 +2139,9 @@ activity type (in English) within the context of the given
|
||||
<p>Subclasses should override get_name(); not this.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_description">get_instance_description()</a></dt></h4><dd>
|
||||
<p><span>get_instance_description(self) -> Union[str, Sequence]</span></p>
|
||||
|
||||
<p>Return a description for this game instance, in English.</p>
|
||||
|
||||
<p>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().</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><span><em><small># this will give us something like 'Score 3 goals.' in English</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># have to be a translation entry for each specific number. ew.</small></em></span>
|
||||
return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]</pre>
|
||||
|
||||
<p>This way the first string can be consistently translated, with any arg
|
||||
values then substituted into the result. ${ARG1} will be replaced with
|
||||
the first value, ${ARG2} with the second, etc.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a></dt></h4><dd>
|
||||
<p><span>get_instance_display_string(self) -> <a href="#class_ba_Lstr">ba.Lstr</a></span></p>
|
||||
|
||||
<p>Return a name for this particular game instance.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a></dt></h4><dd>
|
||||
<p><span>get_instance_scoreboard_description(self) -> Union[str, Sequence]</span></p>
|
||||
|
||||
<p>Return a short description for this game instance in English.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><span><em><small># this will give us something like 'score 3 goals' in English</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># have to be a translation entry for each specific number. ew.</small></em></span>
|
||||
return ['score ${ARG1} goals', self.settings_raw['Score to Win']]</pre>
|
||||
|
||||
<p>This way the first string can be consistently translated, with any arg
|
||||
values then substituted into the result. ${ARG1} will be replaced
|
||||
with the first value, ${ARG2} with the second, etc.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a></dt></h4><dd>
|
||||
<p><span>get_instance_scoreboard_display_string(self) -> <a href="#class_ba_Lstr">ba.Lstr</a></span></p>
|
||||
|
||||
<p>Return a name for this particular game instance.</p>
|
||||
|
||||
<p>This name is used above the game scoreboard in the corner
|
||||
of the screen, so it should be as concise as possible.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_name">get_name()</a></dt></h4><dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_game_settings">get_game_settings()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_name() -> str </span></p>
|
||||
|
||||
<p>Return a str name for this game type.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_score_info">get_score_info()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_score_info() -> <a href="#class_ba_ScoreInfo">ba.ScoreInfo</a> </span></p>
|
||||
|
||||
<p>Return info about game scoring setup; can be overridden by games.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_settings">get_settings()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_settings(sessiontype: Type[<a href="#class_ba_Session">ba.Session</a>]) -> List[Tuple[str, Dict[str, Any]]] </span></p>
|
||||
<p><span>get_game_settings(sessiontype: Type[<a href="#class_ba_Session">ba.Session</a>]) -> List[Tuple[str, Dict[str, Any]]] </span></p>
|
||||
|
||||
<p>Called by the default <a href="#method_ba_GameActivity__create_config_ui">ba.GameActivity.create_config_ui</a>()
|
||||
implementation; should return a dict of config options to be presented
|
||||
@ -2244,9 +2163,9 @@ of a name and a dict of options.</p>
|
||||
|
||||
<p>'increment': Value increment for int/float settings.</p>
|
||||
|
||||
<pre><span><em><small># example get_settings() implementation for a capture-the-flag game:</small></em></span>
|
||||
<pre><span><em><small># example get_game_settings() for a capture-the-flag game:</small></em></span>
|
||||
@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
|
||||
})]</pre>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_description">get_instance_description()</a></dt></h4><dd>
|
||||
<p><span>get_instance_description(self) -> Union[str, Sequence]</span></p>
|
||||
|
||||
<p>Return a description for this game instance, in English.</p>
|
||||
|
||||
<p>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().</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><span><em><small># This will give us something like 'Score 3 goals.' in English</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># have to be a translation entry for each specific number. ew.</small></em></span>
|
||||
return ['Score ${ARG1} goals.', self.settings_raw['Score to Win']]</pre>
|
||||
|
||||
<p>This way the first string can be consistently translated, with any arg
|
||||
values then substituted into the result. ${ARG1} will be replaced with
|
||||
the first value, ${ARG2} with the second, etc.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a></dt></h4><dd>
|
||||
<p><span>get_instance_description_short(self) -> Union[str, Sequence]</span></p>
|
||||
|
||||
<p>Return a short description for this game instance in English.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre><span><em><small># This will give us something like 'score 3 goals' in English</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># have to be a translation entry for each specific number. ew.</small></em></span>
|
||||
return ['score ${ARG1} goals', self.settings_raw['Score to Win']]</pre>
|
||||
|
||||
<p>This way the first string can be consistently translated, with any arg
|
||||
values then substituted into the result. ${ARG1} will be replaced
|
||||
with the first value, ${ARG2} with the second, etc.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a></dt></h4><dd>
|
||||
<p><span>get_instance_display_string(self) -> <a href="#class_ba_Lstr">ba.Lstr</a></span></p>
|
||||
|
||||
<p>Return a name for this particular game instance.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a></dt></h4><dd>
|
||||
<p><span>get_instance_scoreboard_display_string(self) -> <a href="#class_ba_Lstr">ba.Lstr</a></span></p>
|
||||
|
||||
<p>Return a name for this particular game instance.</p>
|
||||
|
||||
<p>This name is used above the game scoreboard in the corner
|
||||
of the screen, so it should be as concise as possible.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_name">get_name()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_name() -> str </span></p>
|
||||
|
||||
<p>Return a str name for this game type.</p>
|
||||
|
||||
<p>This default implementation simply returns the 'name' class attr.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_score_info">get_score_info()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
<p><span>get_score_info() -> <a href="#class_ba_ScoreInfo">ba.ScoreInfo</a> </span></p>
|
||||
|
||||
<p>Return info about game scoring setup; can be overridden by games.</p>
|
||||
|
||||
</dd>
|
||||
<dt><h4><a name="method_ba_GameActivity__get_supported_maps">get_supported_maps()</a></dt></h4><dd>
|
||||
<h5><span><em><class method></span></em></h5>
|
||||
@ -4810,7 +4814,7 @@ of the session.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods Inherited:</h3>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_description">get_instance_scoreboard_description()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_settings">get_settings()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h5><a href="#method_ba_GameActivity__add_actor_weak_ref">add_actor_weak_ref()</a>, <a href="#method_ba_GameActivity__add_player">add_player()</a>, <a href="#method_ba_GameActivity__add_team">add_team()</a>, <a href="#method_ba_GameActivity__begin">begin()</a>, <a href="#method_ba_GameActivity__continue_or_end_game">continue_or_end_game()</a>, <a href="#method_ba_GameActivity__create_config_ui">create_config_ui()</a>, <a href="#method_ba_GameActivity__create_player">create_player()</a>, <a href="#method_ba_GameActivity__create_team">create_team()</a>, <a href="#method_ba_GameActivity__dep_is_present">dep_is_present()</a>, <a href="#method_ba_GameActivity__destroy">destroy()</a>, <a href="#method_ba_GameActivity__end_game">end_game()</a>, <a href="#method_ba_GameActivity__get_config_display_string">get_config_display_string()</a>, <a href="#method_ba_GameActivity__get_description">get_description()</a>, <a href="#method_ba_GameActivity__get_description_display_string">get_description_display_string()</a>, <a href="#method_ba_GameActivity__get_display_string">get_display_string()</a>, <a href="#method_ba_GameActivity__get_dynamic_deps">get_dynamic_deps()</a>, <a href="#method_ba_GameActivity__get_game_settings">get_game_settings()</a>, <a href="#method_ba_GameActivity__get_instance_description">get_instance_description()</a>, <a href="#method_ba_GameActivity__get_instance_description_short">get_instance_description_short()</a>, <a href="#method_ba_GameActivity__get_instance_display_string">get_instance_display_string()</a>, <a href="#method_ba_GameActivity__get_instance_scoreboard_display_string">get_instance_scoreboard_display_string()</a>, <a href="#method_ba_GameActivity__get_name">get_name()</a>, <a href="#method_ba_GameActivity__get_score_info">get_score_info()</a>, <a href="#method_ba_GameActivity__get_supported_maps">get_supported_maps()</a>, <a href="#method_ba_GameActivity__get_team_display_string">get_team_display_string()</a>, <a href="#method_ba_GameActivity__handlemessage">handlemessage()</a>, <a href="#method_ba_GameActivity__has_begun">has_begun()</a>, <a href="#method_ba_GameActivity__has_ended">has_ended()</a>, <a href="#method_ba_GameActivity__has_transitioned_in">has_transitioned_in()</a>, <a href="#method_ba_GameActivity__is_transitioning_out">is_transitioning_out()</a>, <a href="#method_ba_GameActivity__is_waiting_for_continue">is_waiting_for_continue()</a>, <a href="#method_ba_GameActivity__on_continue">on_continue()</a>, <a href="#method_ba_GameActivity__on_expire">on_expire()</a>, <a href="#method_ba_GameActivity__on_player_join">on_player_join()</a>, <a href="#method_ba_GameActivity__on_player_leave">on_player_leave()</a>, <a href="#method_ba_GameActivity__on_team_join">on_team_join()</a>, <a href="#method_ba_GameActivity__on_team_leave">on_team_leave()</a>, <a href="#method_ba_GameActivity__on_transition_out">on_transition_out()</a>, <a href="#method_ba_GameActivity__project_flag_stand">project_flag_stand()</a>, <a href="#method_ba_GameActivity__remove_player">remove_player()</a>, <a href="#method_ba_GameActivity__remove_team">remove_team()</a>, <a href="#method_ba_GameActivity__respawn_player">respawn_player()</a>, <a href="#method_ba_GameActivity__retain_actor">retain_actor()</a>, <a href="#method_ba_GameActivity__set_has_ended">set_has_ended()</a>, <a href="#method_ba_GameActivity__set_immediate_end">set_immediate_end()</a>, <a href="#method_ba_GameActivity__setup_standard_powerup_drops">setup_standard_powerup_drops()</a>, <a href="#method_ba_GameActivity__setup_standard_time_limit">setup_standard_time_limit()</a>, <a href="#method_ba_GameActivity__show_info">show_info()</a>, <a href="#method_ba_GameActivity__show_scoreboard_info">show_scoreboard_info()</a>, <a href="#method_ba_GameActivity__show_zoom_message">show_zoom_message()</a>, <a href="#method_ba_GameActivity__spawn_player">spawn_player()</a>, <a href="#method_ba_GameActivity__spawn_player_if_exists">spawn_player_if_exists()</a>, <a href="#method_ba_GameActivity__transition_in">transition_in()</a>, <a href="#method_ba_GameActivity__transition_out">transition_out()</a></h5>
|
||||
<h3>Methods Defined or Overridden:</h3>
|
||||
<h5><a href="#method_ba_TeamGameActivity____init__"><constructor></a>, <a href="#method_ba_TeamGameActivity__end">end()</a>, <a href="#method_ba_TeamGameActivity__on_begin">on_begin()</a>, <a href="#method_ba_TeamGameActivity__on_transition_in">on_transition_in()</a>, <a href="#method_ba_TeamGameActivity__spawn_player_spaz">spawn_player_spaz()</a>, <a href="#method_ba_TeamGameActivity__supports_session_type">supports_session_type()</a></h5>
|
||||
<dl>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user