diff --git a/assets/src/ba_data/python/ba/_gameactivity.py b/assets/src/ba_data/python/ba/_gameactivity.py index 02b34008..fb418c0b 100644 --- a/assets/src/ba_data/python/ba/_gameactivity.py +++ b/assets/src/ba_data/python/ba/_gameactivity.py @@ -1012,7 +1012,7 @@ class GameActivity(Activity[PlayerType, TeamType]): def spawn_player_spaz(self, player: PlayerType, position: Sequence[float] = (0, 0, 0), - angle: float = None) -> PlayerSpaz[PlayerType]: + angle: float = None) -> PlayerSpaz: """Create and wire up a ba.PlayerSpaz for the provided ba.Player.""" # pylint: disable=too-many-locals # pylint: disable=cyclic-import diff --git a/assets/src/ba_data/python/ba/_teamgame.py b/assets/src/ba_data/python/ba/_teamgame.py index bb149d3a..128b959b 100644 --- a/assets/src/ba_data/python/ba/_teamgame.py +++ b/assets/src/ba_data/python/ba/_teamgame.py @@ -110,7 +110,7 @@ class TeamGameActivity(GameActivity[PlayerType, TeamType]): def spawn_player_spaz(self, player: PlayerType, position: Sequence[float] = None, - angle: float = None) -> PlayerSpaz[PlayerType]: + angle: float = None) -> PlayerSpaz: """ Method override; spawns and wires up a standard ba.PlayerSpaz for a ba.Player. diff --git a/assets/src/ba_data/python/bastd/actor/playerspaz.py b/assets/src/ba_data/python/bastd/actor/playerspaz.py index ea346360..6948c98f 100644 --- a/assets/src/ba_data/python/bastd/actor/playerspaz.py +++ b/assets/src/ba_data/python/bastd/actor/playerspaz.py @@ -22,13 +22,14 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Generic, TypeVar +from typing import TYPE_CHECKING, TypeVar, overload import ba from bastd.actor.spaz import Spaz if TYPE_CHECKING: - from typing import Any, Sequence, Tuple, Optional + from typing import Any, Sequence, Tuple, Optional, Type + from typing_extensions import Literal PlayerType = TypeVar('PlayerType', bound=ba.Player) TeamType = TypeVar('TeamType', bound=ba.Team) @@ -50,7 +51,7 @@ class PlayerSpazHurtMessage: self.spaz = spaz -class PlayerSpaz(Spaz, Generic[PlayerType]): +class PlayerSpaz(Spaz): """A ba.Spaz subclass meant to be controlled by a ba.Player. category: Gameplay Classes @@ -64,7 +65,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): """ def __init__(self, - player: PlayerType, + player: ba.Player, color: Sequence[float] = (1.0, 1.0, 1.0), highlight: Sequence[float] = (0.5, 0.5, 0.5), character: str = 'Spaz', @@ -81,31 +82,51 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): source_player=player, start_invincible=True, powerups_expire=powerups_expire) - self.last_player_attacked_by: Optional[PlayerType] = None + self.last_player_attacked_by: Optional[ba.Player] = None self.last_attacked_time = 0.0 self.last_attacked_type: Optional[Tuple[str, str]] = None self.held_count = 0 - self.last_player_held_by: Optional[PlayerType] = None + self.last_player_held_by: Optional[ba.Player] = None self._player = player self._drive_player_position() - @property - def player(self) -> PlayerType: - """The ba.Player associated with this Spaz. + # @property + # def player(self, playertype: Type[PlayerType]) -> PlayerType: + # """The ba.Player associated with this Spaz. - If the player no longer exists, raises an ba.PlayerNotFoundError. - """ - if not self._player: - raise ba.PlayerNotFoundError() - return self._player + # If the player no longer exists, raises an ba.PlayerNotFoundError. + # """ + # player = self._player + # assert isinstance(player, playertype) + # if not player: + # raise ba.PlayerNotFoundError() + # return player - def getplayer(self) -> Optional[PlayerType]: + @overload + def getplayer(self, + playertype: Type[PlayerType], + doraise: Literal[False] = False) -> Optional[PlayerType]: + ... + + @overload + def getplayer(self, playertype: Type[PlayerType], + doraise: Literal[True]) -> PlayerType: + ... + + def getplayer(self, + playertype: Type[PlayerType], + doraise: bool = False) -> Optional[PlayerType]: """Get the ba.Player associated with this Spaz. - Note that this may return None if the player has left. + By default this will return None if the Player no longer exists. + If you are logically certain that the Player still exists, pass + doraise=False to get a non-optional return type. """ - # Return None in the case of a no-longer-valid reference. - return self._player if self._player else None + player: Any = self._player + assert isinstance(player, playertype) + if not player.exists() and doraise: + raise ba.PlayerNotFoundError() + return player if player.exists() else None def connect_controls_to_player(self, enable_jump: bool = True, @@ -120,7 +141,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): but can be selectively limited by passing False to specific arguments. """ - player = self.getplayer() + player = self.getplayer(ba.Player) assert player # Reset any currently connected player and/or the player we're @@ -232,6 +253,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): activity = self._activity() + player = self.getplayer(ba.Player, doraise=False) if not killed: killerplayer = None else: @@ -254,7 +276,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): # ok, call it a suicide unless we're in co-op if (activity is not None and not isinstance( activity.session, ba.CoopSession)): - killerplayer = self.getplayer() + killerplayer = player else: killerplayer = None @@ -263,9 +285,9 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): assert killerplayer is None or killerplayer # Only report if both the player and the activity still exist. - if killed and activity is not None and self.getplayer(): + if killed and activity is not None and player: activity.handlemessage( - ba.PlayerDiedMessage(self.player, killed, killerplayer, + ba.PlayerDiedMessage(player, killed, killerplayer, msg.how)) super().handlemessage(msg) # Augment standard behavior. @@ -279,7 +301,7 @@ class PlayerSpaz(Spaz, Generic[PlayerType]): self.last_attacked_type = (msg.hit_type, msg.hit_subtype) super().handlemessage(msg) # Augment standard behavior. activity = self._activity() - if activity is not None: + if activity is not None and self._player.exists(): activity.handlemessage(PlayerSpazHurtMessage(self)) else: super().handlemessage(msg) diff --git a/assets/src/ba_data/python/bastd/game/assault.py b/assets/src/ba_data/python/bastd/game/assault.py index 62c30758..6b402b88 100644 --- a/assets/src/ba_data/python/bastd/game/assault.py +++ b/assets/src/ba_data/python/bastd/game/assault.py @@ -187,12 +187,10 @@ class AssaultGame(ba.TeamGameActivity[Player, Team]): if not isinstance(actor, PlayerSpaz): return - player = actor.getplayer() + player = actor.getplayer(Player) if not player or not player.actor: return - assert isinstance(player, Player) - # If its another team's player, they scored. player_team = player.team if player_team is not team: diff --git a/assets/src/ba_data/python/bastd/game/capturetheflag.py b/assets/src/ba_data/python/bastd/game/capturetheflag.py index f8240bab..e897797a 100644 --- a/assets/src/ba_data/python/bastd/game/capturetheflag.py +++ b/assets/src/ba_data/python/bastd/game/capturetheflag.py @@ -170,7 +170,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): self._time_limit = float(settings['Time Limit']) self.flag_touch_return_time = float(settings['Flag Touch Return Time']) - self.flag_idle_return_time = float(settings['Flag Idle return Time']) + self.flag_idle_return_time = float(settings['Flag Idle Return Time']) # Base class overrides self.slow_motion = self._epic_mode @@ -448,7 +448,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): delegate = node.getdelegate() if not isinstance(delegate, PlayerSpaz): return None - return delegate.getplayer() + return delegate.getplayer(Player) def _handle_hit_own_flag(self, team: Team, val: int) -> None: """ @@ -508,10 +508,10 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]): def spawn_player_spaz(self, player: Player, position: Sequence[float] = None, - angle: float = None) -> PlayerSpaz[Player]: + angle: float = None) -> PlayerSpaz: """Intercept new spazzes and add our team material for them.""" spaz = super().spawn_player_spaz(player, position, angle) - player = spaz.player + player = spaz.getplayer(Player, doraise=True) team: Team = player.team player.touching_own_flag = 0 no_physical_mats: List[ba.Material] = [ diff --git a/assets/src/ba_data/python/bastd/game/chosenone.py b/assets/src/ba_data/python/bastd/game/chosenone.py index 085d146b..bc1e2394 100644 --- a/assets/src/ba_data/python/bastd/game/chosenone.py +++ b/assets/src/ba_data/python/bastd/game/chosenone.py @@ -30,6 +30,7 @@ from typing import TYPE_CHECKING import ba from bastd.actor.flag import Flag from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Type, List, Dict, Optional, Sequence, Union @@ -94,7 +95,6 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('keep_away') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._chosen_one_player: Optional[Player] = None @@ -179,7 +179,7 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]): return delegate = ba.get_collision_info('opposing_node').getdelegate() if isinstance(delegate, PlayerSpaz): - player = ba.playercast_o(Player, delegate.getplayer()) + player = delegate.getplayer(Player) if player is not None and player.is_alive(): self._set_chosen_one_player(player) diff --git a/assets/src/ba_data/python/bastd/game/conquest.py b/assets/src/ba_data/python/bastd/game/conquest.py index bdf439a8..0f301525 100644 --- a/assets/src/ba_data/python/bastd/game/conquest.py +++ b/assets/src/ba_data/python/bastd/game/conquest.py @@ -30,6 +30,7 @@ from typing import TYPE_CHECKING import ba from bastd.actor.flag import Flag +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Optional, Type, List, Dict, Sequence, Union @@ -116,7 +117,6 @@ class ConquestGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('conquest') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._score_sound = ba.getsound('score') diff --git a/assets/src/ba_data/python/bastd/game/deathmatch.py b/assets/src/ba_data/python/bastd/game/deathmatch.py index cccac016..2c2395d6 100644 --- a/assets/src/ba_data/python/bastd/game/deathmatch.py +++ b/assets/src/ba_data/python/bastd/game/deathmatch.py @@ -29,6 +29,7 @@ from typing import TYPE_CHECKING import ba from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional @@ -101,7 +102,6 @@ class DeathMatchGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('melee') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._score_to_win: Optional[int] = None diff --git a/assets/src/ba_data/python/bastd/game/easteregghunt.py b/assets/src/ba_data/python/bastd/game/easteregghunt.py index af902c42..e8b21055 100644 --- a/assets/src/ba_data/python/bastd/game/easteregghunt.py +++ b/assets/src/ba_data/python/bastd/game/easteregghunt.py @@ -142,8 +142,7 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]): assert isinstance(egg, Egg) spaz = playernode.getdelegate() assert isinstance(spaz, PlayerSpaz) - player = (spaz.getplayer() - if hasattr(spaz, 'getplayer') else None) + player = spaz.getplayer(Player) if player and egg: player.team.score += 1 diff --git a/assets/src/ba_data/python/bastd/game/elimination.py b/assets/src/ba_data/python/bastd/game/elimination.py index 56fd6843..3bebe0d2 100644 --- a/assets/src/ba_data/python/bastd/game/elimination.py +++ b/assets/src/ba_data/python/bastd/game/elimination.py @@ -29,6 +29,7 @@ from typing import TYPE_CHECKING import ba from bastd.actor.spaz import get_factory +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import (Any, Tuple, Dict, Type, List, Sequence, Optional, @@ -237,7 +238,6 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('melee') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._start_time: Optional[float] = None diff --git a/assets/src/ba_data/python/bastd/game/hockey.py b/assets/src/ba_data/python/bastd/game/hockey.py index e36748b7..5cf8c564 100644 --- a/assets/src/ba_data/python/bastd/game/hockey.py +++ b/assets/src/ba_data/python/bastd/game/hockey.py @@ -28,13 +28,15 @@ from __future__ import annotations from typing import TYPE_CHECKING import ba +from bastd.actor.scoreboard import Scoreboard +from bastd.actor import powerupbox if TYPE_CHECKING: from typing import Any, Sequence, Dict, Type, List, Optional, Union class PuckDeathMessage: - """Inform an object that a puck has died.""" + """Inform something that a puck has died.""" def __init__(self, puck: Puck): self.puck = puck @@ -145,8 +147,6 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('hockey') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard - from bastd.actor import powerupbox super().__init__(settings) self._scoreboard = Scoreboard() self._cheer_sound = ba.getsound('cheer') diff --git a/assets/src/ba_data/python/bastd/game/keepaway.py b/assets/src/ba_data/python/bastd/game/keepaway.py index 15fbfc24..31e9a407 100644 --- a/assets/src/ba_data/python/bastd/game/keepaway.py +++ b/assets/src/ba_data/python/bastd/game/keepaway.py @@ -30,6 +30,7 @@ from typing import TYPE_CHECKING import ba from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard from bastd.actor.flag import (Flag, FlagDroppedMessage, FlagDeathMessage, FlagPickedUpMessage) @@ -89,7 +90,6 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('keep_away') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._swipsound = ba.getsound('swip') diff --git a/assets/src/ba_data/python/bastd/game/kingofthehill.py b/assets/src/ba_data/python/bastd/game/kingofthehill.py index de9192ad..4aea7d06 100644 --- a/assets/src/ba_data/python/bastd/game/kingofthehill.py +++ b/assets/src/ba_data/python/bastd/game/kingofthehill.py @@ -250,7 +250,7 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]): delegate = ba.get_collision_info('opposing_node').getdelegate() if not isinstance(delegate, PlayerSpaz): return - player = ba.playercast_o(Player, delegate.getplayer()) + player = delegate.getplayer(Player) if not player: return diff --git a/assets/src/ba_data/python/bastd/game/ninjafight.py b/assets/src/ba_data/python/bastd/game/ninjafight.py index ba9c964b..8176178f 100644 --- a/assets/src/ba_data/python/bastd/game/ninjafight.py +++ b/assets/src/ba_data/python/bastd/game/ninjafight.py @@ -29,7 +29,7 @@ import random from typing import TYPE_CHECKING import ba -from bastd.actor import spazbot +from bastd.actor.spazbot import BotSet, ChargerBot, SpazBotDeathMessage from bastd.actor.onscreentimer import OnScreenTimer if TYPE_CHECKING: @@ -76,7 +76,7 @@ class NinjaFightGame(ba.TeamGameActivity[Player, Team]): self._winsound = ba.getsound('score') self._won = False self._timer: Optional[OnScreenTimer] = None - self._bots = spazbot.BotSet() + self._bots = BotSet() # Called when our game is transitioning in but not ready to begin; # we can go ahead and start creating stuff, playing music, etc. @@ -100,27 +100,27 @@ class NinjaFightGame(ba.TeamGameActivity[Player, Team]): # Spawn some baddies. ba.timer( 1.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(3, 3, -2), spawn_time=3.0)) + ChargerBot, pos=(3, 3, -2), spawn_time=3.0)) ba.timer( 2.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(-3, 3, -2), spawn_time=3.0)) + ChargerBot, pos=(-3, 3, -2), spawn_time=3.0)) ba.timer( 3.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(5, 3, -2), spawn_time=3.0)) + ChargerBot, pos=(5, 3, -2), spawn_time=3.0)) ba.timer( 4.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(-5, 3, -2), spawn_time=3.0)) + ChargerBot, pos=(-5, 3, -2), spawn_time=3.0)) # Add some extras for multiplayer or pro mode. assert self.initial_player_info is not None if len(self.initial_player_info) > 2 or is_pro: ba.timer( 5.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(0, 3, -5), spawn_time=3.0)) + ChargerBot, pos=(0, 3, -5), spawn_time=3.0)) if len(self.initial_player_info) > 3 or is_pro: ba.timer( 6.0, lambda: self._bots.spawn_bot( - spazbot.ChargerBot, pos=(0, 3, 1), spawn_time=3.0)) + ChargerBot, pos=(0, 3, 1), spawn_time=3.0)) # Called for each spawning player. def spawn_player(self, player: Player) -> ba.Actor: @@ -150,7 +150,7 @@ class NinjaFightGame(ba.TeamGameActivity[Player, Team]): self.respawn_player(msg.getplayer(Player)) # A spaz-bot has died. - elif isinstance(msg, spazbot.SpazBotDeathMessage): + elif isinstance(msg, SpazBotDeathMessage): # Unfortunately the bot-set will always tell us there are living # bots if we ask here (the currently-dying bot isn't officially # marked dead yet) ..so lets push a call into the event loop to diff --git a/assets/src/ba_data/python/bastd/game/onslaught.py b/assets/src/ba_data/python/bastd/game/onslaught.py index 8f58c609..e48c74fe 100644 --- a/assets/src/ba_data/python/bastd/game/onslaught.py +++ b/assets/src/ba_data/python/bastd/game/onslaught.py @@ -30,17 +30,28 @@ import random from typing import TYPE_CHECKING import ba -from bastd.actor import bomb as stdbomb -from bastd.actor import playerspaz, spazbot +from bastd.actor.bomb import TNTSpawner +from bastd.actor.playerspaz import PlayerSpazHurtMessage +from bastd.actor.scoreboard import Scoreboard +from bastd.actor.spazbot import ( + SpazBotDeathMessage, BotSet, ChargerBot, StickyBot, BomberBot, + BomberBotLite, BrawlerBot, BrawlerBotLite, TriggerBot, BomberBotStaticLite, + TriggerBotStatic, BomberBotProStatic, TriggerBotPro, ExplodeyBot, + BrawlerBotProShielded, ChargerBotProShielded, BomberBotPro, + TriggerBotProShielded, BrawlerBotPro, BomberBotProShielded) if TYPE_CHECKING: from typing import Any, Type, Dict, Optional, List, Tuple, Union, Sequence - from bastd.actor.scoreboard import Scoreboard + from bastd.actor.spazbot import SpazBot class Player(ba.Player['Team']): """Our player type for this game.""" + def __init__(self) -> None: + self.has_been_hurt = False + self.respawn_wave = 0 + class Team(ba.Team[Player]): """Our team type for this game.""" @@ -114,8 +125,8 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._have_tnt = False self._excludepowerups: Optional[List[str]] = None self._waves: Optional[List[Dict[str, Any]]] = None - self._tntspawner: Optional[stdbomb.TNTSpawner] = None - self._bots: Optional[spazbot.BotSet] = None + self._tntspawner: Optional[TNTSpawner] = None + self._bots: Optional[BotSet] = None self._powerup_drop_timer: Optional[ba.Timer] = None self._time_bonus_timer: Optional[ba.Timer] = None self._time_bonus_text: Optional[ba.NodeActor] = None @@ -127,17 +138,13 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._tnt_kills = 0 def on_transition_in(self) -> None: - from bastd.actor.scoreboard import Scoreboard super().on_transition_in() - + session = ba.getsession() # Show special landmine tip on rookie preset. if self._preset in ['rookie', 'rookie_easy']: # Show once per session only (then we revert to regular tips). - if not hasattr(ba.getsession(), - '_g_showed_onslaught_land_mine_tip'): - # pylint: disable=protected-access - ba.getsession( # type: ignore - )._g_showed_onslaught_land_mine_tip = True + if not getattr(session, '_g_showed_onslaught_landmine_tip', False): + setattr(session, '_g_showed_onslaught_landmine_tip', True) self.tips = [{ 'tip': 'Land-mines are a good way' ' to stop speedy enemies.', @@ -148,10 +155,8 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): # Show special tnt tip on pro preset. if self._preset in ['pro', 'pro_easy']: # Show once per session only (then we revert to regular tips). - if not hasattr(ba.getsession(), '_g_showed_onslaught_tnt_tip'): - # pylint: disable=protected-access - ba.getsession( # type: ignore - )._g_showed_onslaught_tnt_tip = True + if not getattr(session, '_g_showed_onslaught_tnt_tip', False): + setattr(session, '_g_showed_onslaught_tnt_tip', True) self.tips = [{ 'tip': 'Take out a group of enemies by\n' 'setting off a bomb near a TNT box.', @@ -162,10 +167,8 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): # Show special curse tip on uber preset. if self._preset in ['uber', 'uber_easy']: # Show once per session only (then we revert to regular tips). - if not hasattr(ba.getsession(), '_g_showed_onslaught_curse_tip'): - # pylint: disable=protected-access - ba.getsession( # type: ignore - )._g_showed_onslaught_curse_tip = True + if not getattr(session, '_g_showed_onslaught_curse_tip', False): + setattr(session, '_g_showed_onslaught_curse_tip', True) self.tips = [{ 'tip': 'Curse boxes turn you into a ticking time bomb.\n' 'The only cure is to quickly grab a health-pack.', @@ -203,38 +206,38 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._waves = [ {'base_angle': 195, 'entries': [ - {'type': spazbot.BomberBotLite, 'spacing': 5}, + {'type': BomberBotLite, 'spacing': 5}, ] * player_count}, {'base_angle': 130, 'entries': [ - {'type': spazbot.BrawlerBotLite, 'spacing': 5}, + {'type': BrawlerBotLite, 'spacing': 5}, ] * player_count}, {'base_angle': 195, 'entries': [ - {'type': spazbot.BomberBotLite, 'spacing': 10}, + {'type': BomberBotLite, 'spacing': 10}, ] * (player_count + 1)}, {'base_angle': 130, 'entries': [ - {'type': spazbot.BrawlerBotLite, 'spacing': 10}, + {'type': BrawlerBotLite, 'spacing': 10}, ] * (player_count + 1)}, {'base_angle': 130, 'entries': [ - {'type': spazbot.BrawlerBotLite, 'spacing': 5} + {'type': BrawlerBotLite, 'spacing': 5} if player_count > 1 else None, - {'type': spazbot.BrawlerBotLite, 'spacing': 5}, + {'type': BrawlerBotLite, 'spacing': 5}, {'type': None, 'spacing': 30}, - {'type': spazbot.BomberBotLite, 'spacing': 5} + {'type': BomberBotLite, 'spacing': 5} if player_count > 3 else None, - {'type': spazbot.BomberBotLite, 'spacing': 5}, + {'type': BomberBotLite, 'spacing': 5}, {'type': None, 'spacing': 30}, - {'type': spazbot.BrawlerBotLite, 'spacing': 5}, - {'type': spazbot.BrawlerBotLite, 'spacing': 5} + {'type': BrawlerBotLite, 'spacing': 5}, + {'type': BrawlerBotLite, 'spacing': 5} if player_count > 2 else None, ]}, {'base_angle': 195, 'entries': [ - {'type': spazbot.TriggerBot, 'spacing': 90}, - {'type': spazbot.TriggerBot, 'spacing': 90} + {'type': TriggerBot, 'spacing': 90}, + {'type': TriggerBot, 'spacing': 90} if player_count > 1 else None, ]}, ] # yapf: disable @@ -244,60 +247,60 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._excludepowerups = ['curse'] self._waves = [ {'entries': [ - {'type': spazbot.ChargerBot, 'point': 'left_upper_more'} + {'type': ChargerBot, 'point': 'left_upper_more'} if player_count > 2 else None, - {'type': spazbot.ChargerBot, 'point': 'left_upper'}, + {'type': ChargerBot, 'point': 'left_upper'}, ]}, {'entries': [ - {'type': spazbot.BomberBotStaticLite, + {'type': BomberBotStaticLite, 'point': 'turret_top_right'}, - {'type': spazbot.BrawlerBotLite, 'point': 'right_upper'}, - {'type': spazbot.BrawlerBotLite, 'point': 'right_lower'} + {'type': BrawlerBotLite, 'point': 'right_upper'}, + {'type': BrawlerBotLite, 'point': 'right_lower'} if player_count > 1 else None, - {'type': spazbot.BomberBotStaticLite, + {'type': BomberBotStaticLite, 'point': 'turret_bottom_right'} if player_count > 2 else None, ]}, {'entries': [ - {'type': spazbot.BomberBotStaticLite, + {'type': BomberBotStaticLite, 'point': 'turret_bottom_left'}, - {'type': spazbot.TriggerBot, 'point': 'left'}, - {'type': spazbot.TriggerBot, 'point': 'left_lower'} + {'type': TriggerBot, 'point': 'left'}, + {'type': TriggerBot, 'point': 'left_lower'} if player_count > 1 else None, - {'type': spazbot.TriggerBot, 'point': 'left_upper'} + {'type': TriggerBot, 'point': 'left_upper'} if player_count > 2 else None, ]}, {'entries': [ - {'type': spazbot.BrawlerBotLite, 'point': 'top_right'}, - {'type': spazbot.BrawlerBot, 'point': 'top_half_right'} + {'type': BrawlerBotLite, 'point': 'top_right'}, + {'type': BrawlerBot, 'point': 'top_half_right'} if player_count > 1 else None, - {'type': spazbot.BrawlerBotLite, 'point': 'top_left'}, - {'type': spazbot.BrawlerBotLite, 'point': 'top_half_left'} + {'type': BrawlerBotLite, 'point': 'top_left'}, + {'type': BrawlerBotLite, 'point': 'top_half_left'} if player_count > 2 else None, - {'type': spazbot.BrawlerBot, 'point': 'top'}, - {'type': spazbot.BomberBotStaticLite, + {'type': BrawlerBot, 'point': 'top'}, + {'type': BomberBotStaticLite, 'point': 'turret_top_middle'}, ]}, {'entries': [ - {'type': spazbot.TriggerBotStatic, + {'type': TriggerBotStatic, 'point': 'turret_bottom_left'}, - {'type': spazbot.TriggerBotStatic, + {'type': TriggerBotStatic, 'point': 'turret_bottom_right'}, - {'type': spazbot.TriggerBot, 'point': 'bottom'}, - {'type': spazbot.TriggerBot, 'point': 'bottom_half_right'} + {'type': TriggerBot, 'point': 'bottom'}, + {'type': TriggerBot, 'point': 'bottom_half_right'} if player_count > 1 else None, - {'type': spazbot.TriggerBot, 'point': 'bottom_half_left'} + {'type': TriggerBot, 'point': 'bottom_half_left'} if player_count > 2 else None, ]}, {'entries': [ - {'type': spazbot.BomberBotStaticLite, + {'type': BomberBotStaticLite, 'point': 'turret_top_left'}, - {'type': spazbot.BomberBotStaticLite, + {'type': BomberBotStaticLite, 'point': 'turret_top_right'}, - {'type': spazbot.ChargerBot, 'point': 'bottom'}, - {'type': spazbot.ChargerBot, 'point': 'bottom_half_left'} + {'type': ChargerBot, 'point': 'bottom'}, + {'type': ChargerBot, 'point': 'bottom_half_left'} if player_count > 1 else None, - {'type': spazbot.ChargerBot, 'point': 'bottom_half_right'} + {'type': ChargerBot, 'point': 'bottom_half_right'} if player_count > 2 else None, ]}, ] # yapf: disable @@ -308,78 +311,78 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._waves = [ {'base_angle': -50, 'entries': [ - {'type': spazbot.BrawlerBot, 'spacing': 12} + {'type': BrawlerBot, 'spacing': 12} if player_count > 3 else None, - {'type': spazbot.BrawlerBot, 'spacing': 12}, - {'type': spazbot.BomberBot, 'spacing': 6}, - {'type': spazbot.BomberBot, 'spacing': 6} + {'type': BrawlerBot, 'spacing': 12}, + {'type': BomberBot, 'spacing': 6}, + {'type': BomberBot, 'spacing': 6} if self._preset == 'pro' else None, - {'type': spazbot.BomberBot, 'spacing': 6} + {'type': BomberBot, 'spacing': 6} if player_count > 1 else None, - {'type': spazbot.BrawlerBot, 'spacing': 12}, - {'type': spazbot.BrawlerBot, 'spacing': 12} + {'type': BrawlerBot, 'spacing': 12}, + {'type': BrawlerBot, 'spacing': 12} if player_count > 2 else None, ]}, {'base_angle': 180, 'entries': [ - {'type': spazbot.BrawlerBot, 'spacing': 6} + {'type': BrawlerBot, 'spacing': 6} if player_count > 3 else None, - {'type': spazbot.BrawlerBot, 'spacing': 6} + {'type': BrawlerBot, 'spacing': 6} if self._preset == 'pro' else None, - {'type': spazbot.BrawlerBot, 'spacing': 6}, - {'type': spazbot.ChargerBot, 'spacing': 45}, - {'type': spazbot.ChargerBot, 'spacing': 45} + {'type': BrawlerBot, 'spacing': 6}, + {'type': ChargerBot, 'spacing': 45}, + {'type': ChargerBot, 'spacing': 45} if player_count > 1 else None, - {'type': spazbot.BrawlerBot, 'spacing': 6}, - {'type': spazbot.BrawlerBot, 'spacing': 6} + {'type': BrawlerBot, 'spacing': 6}, + {'type': BrawlerBot, 'spacing': 6} if self._preset == 'pro' else None, - {'type': spazbot.BrawlerBot, 'spacing': 6} + {'type': BrawlerBot, 'spacing': 6} if player_count > 2 else None, ]}, {'base_angle': 0, 'entries': [ - {'type': spazbot.ChargerBot, 'spacing': 30}, - {'type': spazbot.TriggerBot, 'spacing': 30}, - {'type': spazbot.TriggerBot, 'spacing': 30}, - {'type': spazbot.TriggerBot, 'spacing': 30} + {'type': ChargerBot, 'spacing': 30}, + {'type': TriggerBot, 'spacing': 30}, + {'type': TriggerBot, 'spacing': 30}, + {'type': TriggerBot, 'spacing': 30} if self._preset == 'pro' else None, - {'type': spazbot.TriggerBot, 'spacing': 30} + {'type': TriggerBot, 'spacing': 30} if player_count > 1 else None, - {'type': spazbot.TriggerBot, 'spacing': 30} + {'type': TriggerBot, 'spacing': 30} if player_count > 3 else None, - {'type': spazbot.ChargerBot, 'spacing': 30}, + {'type': ChargerBot, 'spacing': 30}, ]}, {'base_angle': 90, 'entries': [ - {'type': spazbot.StickyBot, 'spacing': 50}, - {'type': spazbot.StickyBot, 'spacing': 50} + {'type': StickyBot, 'spacing': 50}, + {'type': StickyBot, 'spacing': 50} if self._preset == 'pro' else None, - {'type': spazbot.StickyBot, 'spacing': 50}, - {'type': spazbot.StickyBot, 'spacing': 50} + {'type': StickyBot, 'spacing': 50}, + {'type': StickyBot, 'spacing': 50} if player_count > 1 else None, - {'type': spazbot.StickyBot, 'spacing': 50} + {'type': StickyBot, 'spacing': 50} if player_count > 3 else None, ]}, {'base_angle': 0, 'entries': [ - {'type': spazbot.TriggerBot, 'spacing': 72}, - {'type': spazbot.TriggerBot, 'spacing': 72}, - {'type': spazbot.TriggerBot, 'spacing': 72} + {'type': TriggerBot, 'spacing': 72}, + {'type': TriggerBot, 'spacing': 72}, + {'type': TriggerBot, 'spacing': 72} if self._preset == 'pro' else None, - {'type': spazbot.TriggerBot, 'spacing': 72}, - {'type': spazbot.TriggerBot, 'spacing': 72}, - {'type': spazbot.TriggerBot, 'spacing': 36} + {'type': TriggerBot, 'spacing': 72}, + {'type': TriggerBot, 'spacing': 72}, + {'type': TriggerBot, 'spacing': 36} if player_count > 2 else None, ]}, {'base_angle': 30, 'entries': [ - {'type': spazbot.ChargerBotProShielded, 'spacing': 50}, - {'type': spazbot.ChargerBotProShielded, 'spacing': 50}, - {'type': spazbot.ChargerBotProShielded, 'spacing': 50} + {'type': ChargerBotProShielded, 'spacing': 50}, + {'type': ChargerBotProShielded, 'spacing': 50}, + {'type': ChargerBotProShielded, 'spacing': 50} if self._preset == 'pro' else None, - {'type': spazbot.ChargerBotProShielded, 'spacing': 50} + {'type': ChargerBotProShielded, 'spacing': 50} if player_count > 1 else None, - {'type': spazbot.ChargerBotProShielded, 'spacing': 50} + {'type': ChargerBotProShielded, 'spacing': 50} if player_count > 2 else None, ]} ] # yapf: disable @@ -395,84 +398,84 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): self._excludepowerups = [] self._waves = [ {'entries': [ - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_middle_left'} if hard else None, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_middle_right'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_left'} if player_count > 2 else None, - {'type': spazbot.ExplodeyBot, 'point': 'top_right'}, + {'type': ExplodeyBot, 'point': 'top_right'}, {'type': 'delay', 'duration': 4.0}, - {'type': spazbot.ExplodeyBot, 'point': 'top_left'}, + {'type': ExplodeyBot, 'point': 'top_left'}, ]}, {'entries': [ - {'type': spazbot.ChargerBot, 'point': 'left'}, - {'type': spazbot.ChargerBot, 'point': 'right'}, - {'type': spazbot.ChargerBot, 'point': 'right_upper_more'} + {'type': ChargerBot, 'point': 'left'}, + {'type': ChargerBot, 'point': 'right'}, + {'type': ChargerBot, 'point': 'right_upper_more'} if player_count > 2 else None, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_left'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_right'}, ]}, {'entries': [ - {'type': spazbot.TriggerBotPro, 'point': 'top_right'}, - {'type': spazbot.TriggerBotPro, + {'type': TriggerBotPro, 'point': 'top_right'}, + {'type': TriggerBotPro, 'point': 'right_upper_more'} if player_count > 1 else None, - {'type': spazbot.TriggerBotPro, 'point': 'right_upper'}, - {'type': spazbot.TriggerBotPro, 'point': 'right_lower'} + {'type': TriggerBotPro, 'point': 'right_upper'}, + {'type': TriggerBotPro, 'point': 'right_lower'} if hard else None, - {'type': spazbot.TriggerBotPro, + {'type': TriggerBotPro, 'point': 'right_lower_more'} if player_count > 2 else None, - {'type': spazbot.TriggerBotPro, 'point': 'bottom_right'}, + {'type': TriggerBotPro, 'point': 'bottom_right'}, ]}, {'entries': [ - {'type': spazbot.ChargerBotProShielded, + {'type': ChargerBotProShielded, 'point': 'bottom_right'}, - {'type': spazbot.ChargerBotProShielded, 'point': 'bottom'} + {'type': ChargerBotProShielded, 'point': 'bottom'} if player_count > 2 else None, - {'type': spazbot.ChargerBotProShielded, + {'type': ChargerBotProShielded, 'point': 'bottom_left'}, - {'type': spazbot.ChargerBotProShielded, 'point': 'top'} + {'type': ChargerBotProShielded, 'point': 'top'} if hard else None, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_middle'}, ]}, {'entries': [ - {'type': spazbot.ExplodeyBot, 'point': 'left_upper'}, + {'type': ExplodeyBot, 'point': 'left_upper'}, {'type': 'delay', 'duration': 1.0}, - {'type': spazbot.BrawlerBotProShielded, + {'type': BrawlerBotProShielded, 'point': 'left_lower'}, - {'type': spazbot.BrawlerBotProShielded, + {'type': BrawlerBotProShielded, 'point': 'left_lower_more'}, {'type': 'delay', 'duration': 4.0}, - {'type': spazbot.ExplodeyBot, 'point': 'right_upper'}, + {'type': ExplodeyBot, 'point': 'right_upper'}, {'type': 'delay', 'duration': 1.0}, - {'type': spazbot.BrawlerBotProShielded, + {'type': BrawlerBotProShielded, 'point': 'right_lower'}, - {'type': spazbot.BrawlerBotProShielded, + {'type': BrawlerBotProShielded, 'point': 'right_upper_more'}, {'type': 'delay', 'duration': 4.0}, - {'type': spazbot.ExplodeyBot, 'point': 'left'}, + {'type': ExplodeyBot, 'point': 'left'}, {'type': 'delay', 'duration': 5.0}, - {'type': spazbot.ExplodeyBot, 'point': 'right'}, + {'type': ExplodeyBot, 'point': 'right'}, ]}, {'entries': [ - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_left'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_right'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_bottom_left'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_bottom_right'}, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_middle_left'} if hard else None, - {'type': spazbot.BomberBotProStatic, + {'type': BomberBotProStatic, 'point': 'turret_top_middle_right'} if hard else None, ] }] # yapf: disable @@ -498,11 +501,11 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): # Our TNT spawner (if applicable). if self._have_tnt: - self._tntspawner = stdbomb.TNTSpawner(position=self._tntspawnpos) + self._tntspawner = TNTSpawner(position=self._tntspawnpos) self.setup_low_life_warning_sound() self._update_scores() - self._bots = spazbot.BotSet() + self._bots = BotSet() ba.timer(4.0, self._start_updating_waves) def _on_got_scores_to_beat(self, scores: List[Dict[str, Any]]) -> None: @@ -852,11 +855,10 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): assert self._waves is not None if (not player.is_alive() and (self._preset in ['endless', 'endless_tournament'] or - (player.gamedata['respawn_wave'] <= len(self._waves)))): + (player.respawn_wave <= len(self._waves)))): rtxt = ba.Lstr(resource='onslaughtRespawnText', subs=[('${PLAYER}', player.get_name()), - ('${WAVE}', - str(player.gamedata['respawn_wave'])) + ('${WAVE}', str(player.respawn_wave)) ]) text = ba.Lstr(value='${A}${B}\n', subs=[ @@ -881,7 +883,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): if self._wave > 1 and not self.is_waiting_for_continue(): for player in self.players: if (not player.is_alive() - and player.gamedata['respawn_wave'] == self._wave): + and player.respawn_wave == self._wave): self.spawn_player(player) self._update_player_spawn_info() self.show_zoom_message(ba.Lstr(value='${A} ${B}', @@ -907,40 +909,34 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): if self._preset in ['endless', 'endless_tournament']: level = self._wave bot_types2 = [ - spazbot.BomberBot, spazbot.BrawlerBot, spazbot.TriggerBot, - spazbot.ChargerBot, spazbot.BomberBotPro, - spazbot.BrawlerBotPro, spazbot.TriggerBotPro, - spazbot.BomberBotProShielded, spazbot.ExplodeyBot, - spazbot.ChargerBotProShielded, spazbot.StickyBot, - spazbot.BrawlerBotProShielded, spazbot.TriggerBotProShielded + BomberBot, BrawlerBot, TriggerBot, ChargerBot, BomberBotPro, + BrawlerBotPro, TriggerBotPro, BomberBotProShielded, + ExplodeyBot, ChargerBotProShielded, StickyBot, + BrawlerBotProShielded, TriggerBotProShielded ] if level > 5: bot_types2 += [ - spazbot.ExplodeyBot, - spazbot.TriggerBotProShielded, - spazbot.BrawlerBotProShielded, - spazbot.ChargerBotProShielded, + ExplodeyBot, + TriggerBotProShielded, + BrawlerBotProShielded, + ChargerBotProShielded, ] if level > 7: bot_types2 += [ - spazbot.ExplodeyBot, - spazbot.TriggerBotProShielded, - spazbot.BrawlerBotProShielded, - spazbot.ChargerBotProShielded, + ExplodeyBot, + TriggerBotProShielded, + BrawlerBotProShielded, + ChargerBotProShielded, ] if level > 10: bot_types2 += [ - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded + TriggerBotProShielded, TriggerBotProShielded, + TriggerBotProShielded, TriggerBotProShielded ] if level > 13: bot_types2 += [ - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded, - spazbot.TriggerBotProShielded + TriggerBotProShielded, TriggerBotProShielded, + TriggerBotProShielded, TriggerBotProShielded ] bot_levels = [[b for b in bot_types2 if b.points_mult == 1], @@ -1096,7 +1092,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): def add_bot_at_point(self, point: str, - spaz_type: Type[spazbot.SpazBot], + spaz_type: Type[SpazBot], spawn_time: float = 1.0) -> None: """Add a new bot at a specified named point.""" if self._game_over: @@ -1107,7 +1103,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): def add_bot_at_angle(self, angle: float, - spaz_type: Type[spazbot.SpazBot], + spaz_type: Type[SpazBot], spawn_time: float = 1.0) -> None: """Add a new bot at a specified angle (for circular maps).""" if self._game_over: @@ -1153,11 +1149,9 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): # pylint: disable=too-many-statements # pylint: disable=too-many-branches - if isinstance(msg, playerspaz.PlayerSpazHurtMessage): - player = msg.spaz.getplayer() - if not player: - return - player.gamedata['has_been_hurt'] = True + if isinstance(msg, PlayerSpazHurtMessage): + player = msg.spaz.getplayer(Player, doraise=True) + player.has_been_hurt = True self._a_player_has_been_hurt = True elif isinstance(msg, ba.PlayerScoredMessage): @@ -1171,15 +1165,15 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]): # Make note with the player when they can respawn: if self._wave < 10: - player.gamedata['respawn_wave'] = max(2, self._wave + 1) + player.respawn_wave = max(2, self._wave + 1) elif self._wave < 15: - player.gamedata['respawn_wave'] = max(2, self._wave + 2) + player.respawn_wave = max(2, self._wave + 2) else: - player.gamedata['respawn_wave'] = max(2, self._wave + 3) + player.respawn_wave = max(2, self._wave + 3) ba.timer(0.1, self._update_player_spawn_info) ba.timer(0.1, self._checkroundover) - elif isinstance(msg, spazbot.SpazBotDeathMessage): + elif isinstance(msg, SpazBotDeathMessage): pts, importance = msg.badguy.get_death_points(msg.how) if msg.killerplayer is not None: diff --git a/assets/src/ba_data/python/bastd/game/race.py b/assets/src/ba_data/python/bastd/game/race.py index 14b875ec..05bc93f0 100644 --- a/assets/src/ba_data/python/bastd/game/race.py +++ b/assets/src/ba_data/python/bastd/game/race.py @@ -32,6 +32,7 @@ from dataclasses import dataclass import ba from bastd.actor.bomb import Bomb from bastd.actor.playerspaz import PlayerSpaz +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict, @@ -143,7 +144,6 @@ class RaceGame(ba.TeamGameActivity[Player, Team]): return ba.getmaps('race') def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard self._race_started = False super().__init__(settings) self._scoreboard = Scoreboard() diff --git a/assets/src/ba_data/python/bastd/game/targetpractice.py b/assets/src/ba_data/python/bastd/game/targetpractice.py index 4a4efaaf..c842750e 100644 --- a/assets/src/ba_data/python/bastd/game/targetpractice.py +++ b/assets/src/ba_data/python/bastd/game/targetpractice.py @@ -29,11 +29,14 @@ import random from typing import TYPE_CHECKING import ba +from bastd.actor.scoreboard import Scoreboard +from bastd.actor.onscreencountdown import OnScreenCountdown +from bastd.actor.bomb import Bomb +from bastd.actor.popuptext import PopupText if TYPE_CHECKING: from typing import Any, Type, List, Dict, Optional, Sequence - from bastd.actor.onscreencountdown import OnScreenCountdown - from bastd.actor.bomb import Bomb, Blast + from bastd.actor.bomb import Blast class Player(ba.Player['Team']): @@ -80,7 +83,6 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): or issubclass(sessiontype, ba.MultiTeamSession)) def __init__(self, settings: Dict[str, Any]): - from bastd.actor.scoreboard import Scoreboard super().__init__(settings) self._scoreboard = Scoreboard() self._targets: List[Target] = [] @@ -98,7 +100,6 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): self.update_scoreboard() def on_begin(self) -> None: - from bastd.actor.onscreencountdown import OnScreenCountdown super().on_begin() self.update_scoreboard() @@ -141,9 +142,9 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): ypos = random.uniform(-1.0, 1.0) if xpos * xpos + ypos * ypos < 1.0: break - points.append((8.0 * xpos, 2.2, -3.5 + 5.0 * ypos)) + points.append(ba.Vec3(8.0 * xpos, 2.2, -3.5 + 5.0 * ypos)) - def get_min_dist_from_target(pnt: Sequence[float]) -> float: + def get_min_dist_from_target(pnt: ba.Vec3) -> float: return min((t.get_dist_from_point(pnt) for t in self._targets)) # If we have existing targets, use the point with the highest @@ -157,7 +158,6 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]): def _on_spaz_dropped_bomb(self, spaz: ba.Actor, bomb: ba.Actor) -> None: del spaz # Unused. - from bastd.actor.bomb import Bomb # Wire up this bomb to inform us when it blows up. assert isinstance(bomb, Bomb) @@ -281,14 +281,13 @@ class Target(ba.Actor): else: super().handlemessage(msg) - def get_dist_from_point(self, pos: Sequence[float]) -> float: + def get_dist_from_point(self, pos: ba.Vec3) -> float: """Given a point, returns distance squared from it.""" - return (ba.Vec3(pos) - self._position).length() + return (pos - self._position).length() def do_hit_at_position(self, pos: Sequence[float], player: Player) -> bool: """Handle a bomb hit at the given position.""" # pylint: disable=too-many-statements - from bastd.actor import popuptext activity = self.activity # Ignore hits if the game is over or if we've already been hit @@ -357,10 +356,10 @@ class Target(ba.Actor): if len(activity.players) > 1: popupcolor = ba.safecolor(player.color, target_intensity=0.75) popupstr += ' ' + player.get_name() - popuptext.PopupText(popupstr, - position=self._position, - color=popupcolor, - scale=popupscale).autoretain() + PopupText(popupstr, + position=self._position, + color=popupcolor, + scale=popupscale).autoretain() # Give this player's team points and update the score-board. player.team.score += points diff --git a/assets/src/ba_data/python/bastd/game/thelaststand.py b/assets/src/ba_data/python/bastd/game/thelaststand.py index 147bd279..e651aae7 100644 --- a/assets/src/ba_data/python/bastd/game/thelaststand.py +++ b/assets/src/ba_data/python/bastd/game/thelaststand.py @@ -26,13 +26,13 @@ import random from typing import TYPE_CHECKING import ba -from bastd.actor import playerspaz from bastd.actor import spazbot +from bastd.actor.playerspaz import PlayerSpaz from bastd.actor.bomb import TNTSpawner +from bastd.actor.scoreboard import Scoreboard if TYPE_CHECKING: from typing import Any, Dict, Type, List, Optional, Sequence - from bastd.actor.scoreboard import Scoreboard class Player(ba.Player['Team']): @@ -59,6 +59,8 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]): # And of course the most important part. slow_motion = True + default_music = ba.MusicType.EPIC + def __init__(self, settings: Dict[str, Any]): settings['map'] = 'Rampage' super().__init__(settings) @@ -98,8 +100,6 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]): } # yapf: disable def on_transition_in(self) -> None: - from bastd.actor.scoreboard import Scoreboard - self.default_music = ba.MusicType.EPIC super().on_transition_in() ba.timer(1.3, ba.Call(ba.playsound, self._new_wave_sound)) self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'), @@ -198,11 +198,11 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]): for player in self.players: try: if player.is_alive(): - assert isinstance(player.actor, playerspaz.PlayerSpaz) + assert isinstance(player.actor, PlayerSpaz) assert player.actor.node playerpts.append(player.actor.node.position) - except Exception as exc: - print('ERROR in _update_bots', exc) + except Exception: + ba.print_exception('Error updating bots') for i in range(3): for playerpt in playerpts: dists[i] += abs(playerpt[0] - botspawnpts[i][0]) @@ -244,7 +244,7 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]): spawntype[1][1] += spawntype[1][2] # incr spawn rate incr rate def _update_scores(self) -> None: - # Achievements in default preset only. + # Do achievements in default preset only. score = self._score if self._preset == 'default': if score >= 250: @@ -298,7 +298,6 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]): super().handlemessage(msg) def _on_got_scores_to_beat(self, scores: List[Dict[str, Any]]) -> None: - # FIXME: Unify args. self._show_standard_scores_to_beat_ui(scores) def end_game(self) -> None: diff --git a/docs/ba_module.md b/docs/ba_module.md index ff8aa38f..795b4dea 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -
This page documents the Python classes and functions in the 'ba' module, which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!
spawn_player_spaz(self, player: PlayerType, position: Sequence[float] = (0, 0, 0), angle: float = None) -> PlayerSpaz[PlayerType]
+spawn_player_spaz(self, player: PlayerType, position: Sequence[float] = (0, 0, 0), angle: float = None) -> PlayerSpaz
Create and wire up a ba.PlayerSpaz for the provided ba.Player.
@@ -4975,7 +4975,7 @@ up until ba.Activity.on_begin() is cspawn_player_spaz(self, player: PlayerType, position: Sequence[float] = None, angle: float = None) -> PlayerSpaz[PlayerType]
+spawn_player_spaz(self, player: PlayerType, position: Sequence[float] = None, angle: float = None) -> PlayerSpaz
Method override; spawns and wires up a standard ba.PlayerSpaz for a ba.Player.