diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml index da52b07d..563dcadb 100644 --- a/.idea/dictionaries/ericf.xml +++ b/.idea/dictionaries/ericf.xml @@ -1752,6 +1752,7 @@ spazappearance spazbot spazfactory + spaztype spazzes spcall spcstr diff --git a/assets/src/ba_data/python/bastd/game/runaround.py b/assets/src/ba_data/python/bastd/game/runaround.py index cf27e920..acccd945 100644 --- a/assets/src/ba_data/python/bastd/game/runaround.py +++ b/assets/src/ba_data/python/bastd/game/runaround.py @@ -26,6 +26,8 @@ from __future__ import annotations import random +from dataclasses import dataclass +from enum import Enum from typing import TYPE_CHECKING import ba @@ -42,7 +44,46 @@ from bastd.actor.spazbot import ( BomberBotPro, BrawlerBotPro) if TYPE_CHECKING: - from typing import Type, Any, List, Dict, Tuple, Sequence, Optional + from typing import Type, Any, List, Dict, Tuple, Sequence, Optional, Union + + +class Preset(Enum): + """Play presets.""" + ENDLESS = 'endless' + ENDLESS_TOURNAMENT = 'endless_tournament' + PRO = 'pro' + PRO_EASY = 'pro_easy' + UBER = 'uber' + UBER_EASY = 'uber_easy' + TOURNAMENT = 'tournament' + TOURNAMENT_UBER = 'tournament_uber' + + +class Point(Enum): + """Where we can spawn stuff and the corresponding map attr name.""" + BOTTOM_LEFT = 'bot_spawn_bottom_left' + BOTTOM_RIGHT = 'bot_spawn_bottom_right' + START = 'bot_spawn_start' + + +@dataclass +class Spawn: + """Defines a bot spawn.""" + type: Type[SpazBot] + path: int = 0 + point: Optional[Point] = None + + +@dataclass +class Spacing: + """Defines spacing between spawns.""" + duration: float + + +@dataclass +class Wave: + """Defines a wave of enemies.""" + entries: List[Union[Spawn, Spacing, None]] class Player(ba.Player['Team']): @@ -90,7 +131,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): settings['map'] = 'Tower D' super().__init__(settings) shared = SharedObjects.get() - self._preset = str(settings.get('preset', 'pro')) + self._preset = Preset(settings.get('preset', 'pro')) self._player_death_sound = ba.getsound('playerDeath') self._new_wave_sound = ba.getsound('scoreHit01') @@ -112,9 +153,11 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): self._score_region_material = ba.Material() self._score_region_material.add_actions( conditions=('they_have_material', shared.player_material), - actions=(('modify_part_collision', 'collide', - True), ('modify_part_collision', 'physical', False), - ('call', 'at_connect', self._handle_reached_end))) + actions=( + ('modify_part_collision', 'collide', True), + ('modify_part_collision', 'physical', False), + ('call', 'at_connect', self._handle_reached_end), + )) self._last_wave_end_time = ba.time() self._player_has_picked_up_powerup = False @@ -129,7 +172,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): self._dingsoundhigh = ba.getsound('dingSmallHigh') self._exclude_powerups: Optional[List[str]] = None self._have_tnt: Optional[bool] = None - self._waves: Optional[List[Dict[str, Any]]] = None + self._waves: Optional[List[Wave]] = None self._bots = SpazBotSet() self._tntspawner: Optional[TNTSpawner] = None self._lives_bg: Optional[ba.NodeActor] = None @@ -161,206 +204,186 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): def on_begin(self) -> None: super().on_begin() player_count = len(self.players) - hard = self._preset not in ['pro_easy', 'uber_easy'] + hard = self._preset not in {Preset.PRO_EASY, Preset.UBER_EASY} - if self._preset in ['pro', 'pro_easy', 'tournament']: + if self._preset in {Preset.PRO, Preset.PRO_EASY, Preset.TOURNAMENT}: self._exclude_powerups = ['curse'] self._have_tnt = True self._waves = [ - {'entries': [ - {'type': BomberBot, 'path': 3 if hard else 2}, - {'type': BomberBot, 'path': 2}, - {'type': BomberBot, 'path': 2} if hard else None, - {'type': BomberBot, 'path': 2} if player_count > 1 - else None, - {'type': BomberBot, 'path': 1} if hard else None, - {'type': BomberBot, 'path': 1} if player_count > 2 - else None, - {'type': BomberBot, 'path': 1} if player_count > 3 - else None, - ]}, - {'entries': [ - {'type': BomberBot, 'path': 1} if hard else None, - {'type': BomberBot, 'path': 2} if hard else None, - {'type': BomberBot, 'path': 2}, - {'type': BomberBot, 'path': 2}, - {'type': BomberBot, 'path': 2} if player_count > 3 - else None, - {'type': BrawlerBot, 'path': 3}, - {'type': BrawlerBot, 'path': 3}, - {'type': BrawlerBot, 'path': 3} if hard else None, - {'type': BrawlerBot, 'path': 3} if player_count > 1 - else None, - {'type': BrawlerBot, 'path': 3} if player_count > 2 - else None, - ]}, - {'entries': [ - {'type': ChargerBot, 'path': 2} if hard else None, - {'type': ChargerBot, 'path': 2} if player_count > 2 - else None, - {'type': TriggerBot, 'path': 2}, - {'type': TriggerBot, 'path': 2} if player_count > 1 - else None, - {'type': 'spacing', 'duration': 3.0}, - {'type': BomberBot, 'path': 2} if hard else None, - {'type': BomberBot, 'path': 2} if hard else None, - {'type': BomberBot, 'path': 2}, - {'type': BomberBot, 'path': 3} if hard else None, - {'type': BomberBot, 'path': 3}, - {'type': BomberBot, 'path': 3}, - {'type': BomberBot, 'path': 3} if player_count > 3 - else None, - ]}, - {'entries': [ - {'type': TriggerBot, 'path': 1} if hard else None, - {'type': 'spacing', 'duration': 1.0} if hard else None, - {'type': TriggerBot, 'path': 2}, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 3}, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 1} if hard else None, - {'type': 'spacing', 'duration': 1.0} if hard else None, - {'type': TriggerBot, 'path': 2}, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 3}, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 1} - if (player_count > 1 and hard) else None, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 2} if player_count > 2 - else None, - {'type': 'spacing', 'duration': 1.0}, - {'type': TriggerBot, 'path': 3} if player_count > 3 - else None, - {'type': 'spacing', 'duration': 1.0}, - ]}, - {'entries': [ - {'type': ChargerBotProShielded if hard - else ChargerBot, 'path': 1}, - {'type': BrawlerBot, 'path': 2} if hard else None, - {'type': BrawlerBot, 'path': 2}, - {'type': BrawlerBot, 'path': 2}, - {'type': BrawlerBot, 'path': 3} if hard else None, - {'type': BrawlerBot, 'path': 3}, - {'type': BrawlerBot, 'path': 3}, - {'type': BrawlerBot, 'path': 3} if player_count > 1 - else None, - {'type': BrawlerBot, 'path': 3} if player_count > 2 - else None, - {'type': BrawlerBot, 'path': 3} if player_count > 3 - else None, - ]}, - {'entries': [ - {'type': BomberBotProShielded, 'path': 3}, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 1} if hard - else None, - {'type': 'spacing', 'duration': 1.0} if hard else None, - {'type': BomberBotProShielded, 'path': 3}, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 1} if hard - else None, - {'type': 'spacing', 'duration': 1.5} if hard else None, - {'type': BomberBotProShielded, 'path': 3} - if player_count > 1 else None, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 2} - if player_count > 2 else None, - {'type': 'spacing', 'duration': 1.5}, - {'type': BomberBotProShielded, 'path': 1} - if player_count > 3 else None, - ]}, - ] # yapf: disable - elif self._preset in ['uber_easy', 'uber', 'tournament_uber']: + Wave(entries=[ + Spawn(BomberBot, path=3 if hard else 2), + Spawn(BomberBot, path=2), + Spawn(BomberBot, path=2) if hard else None, + Spawn(BomberBot, path=2) if player_count > 1 else None, + Spawn(BomberBot, path=1) if hard else None, + Spawn(BomberBot, path=1) if player_count > 2 else None, + Spawn(BomberBot, path=1) if player_count > 3 else None, + ]), + Wave(entries=[ + Spawn(BomberBot, path=1) if hard else None, + Spawn(BomberBot, path=2) if hard else None, + Spawn(BomberBot, path=2), + Spawn(BomberBot, path=2), + Spawn(BomberBot, path=2) if player_count > 3 else None, + Spawn(BrawlerBot, path=3), + Spawn(BrawlerBot, path=3), + Spawn(BrawlerBot, path=3) if hard else None, + Spawn(BrawlerBot, path=3) if player_count > 1 else None, + Spawn(BrawlerBot, path=3) if player_count > 2 else None, + ]), + Wave(entries=[ + Spawn(ChargerBot, path=2) if hard else None, + Spawn(ChargerBot, path=2) if player_count > 2 else None, + Spawn(TriggerBot, path=2), + Spawn(TriggerBot, path=2) if player_count > 1 else None, + Spacing(duration=3.0), + Spawn(BomberBot, path=2) if hard else None, + Spawn(BomberBot, path=2) if hard else None, + Spawn(BomberBot, path=2), + Spawn(BomberBot, path=3) if hard else None, + Spawn(BomberBot, path=3), + Spawn(BomberBot, path=3), + Spawn(BomberBot, path=3) if player_count > 3 else None, + ]), + Wave(entries=[ + Spawn(TriggerBot, path=1) if hard else None, + Spacing(duration=1.0) if hard else None, + Spawn(TriggerBot, path=2), + Spacing(duration=1.0), + Spawn(TriggerBot, path=3), + Spacing(duration=1.0), + Spawn(TriggerBot, path=1) if hard else None, + Spacing(duration=1.0) if hard else None, + Spawn(TriggerBot, path=2), + Spacing(duration=1.0), + Spawn(TriggerBot, path=3), + Spacing(duration=1.0), + Spawn(TriggerBot, path=1) if ( + player_count > 1 and hard) else None, + Spacing(duration=1.0), + Spawn(TriggerBot, path=2) if player_count > 2 else None, + Spacing(duration=1.0), + Spawn(TriggerBot, path=3) if player_count > 3 else None, + Spacing(duration=1.0), + ]), + Wave(entries=[ + Spawn(ChargerBotProShielded if hard else ChargerBot, + path=1), + Spawn(BrawlerBot, path=2) if hard else None, + Spawn(BrawlerBot, path=2), + Spawn(BrawlerBot, path=2), + Spawn(BrawlerBot, path=3) if hard else None, + Spawn(BrawlerBot, path=3), + Spawn(BrawlerBot, path=3), + Spawn(BrawlerBot, path=3) if player_count > 1 else None, + Spawn(BrawlerBot, path=3) if player_count > 2 else None, + Spawn(BrawlerBot, path=3) if player_count > 3 else None, + ]), + Wave(entries=[ + Spawn(BomberBotProShielded, path=3), + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=2), + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=1) if hard else None, + Spacing(duration=1.0) if hard else None, + Spawn(BomberBotProShielded, path=3), + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=2), + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=1) if hard else None, + Spacing(duration=1.5) if hard else None, + Spawn(BomberBotProShielded, path=3 + ) if player_count > 1 else None, + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=2 + ) if player_count > 2 else None, + Spacing(duration=1.5), + Spawn(BomberBotProShielded, path=1 + ) if player_count > 3 else None, + ]), + ] + elif self._preset in { + Preset.UBER_EASY, Preset.UBER, Preset.TOURNAMENT_UBER + }: self._exclude_powerups = [] self._have_tnt = True self._waves = [ - {'entries': [ - {'type': TriggerBot, 'path': 1} if hard else None, - {'type': TriggerBot, 'path': 2}, - {'type': TriggerBot, 'path': 2}, - {'type': TriggerBot, 'path': 3}, - {'type': BrawlerBotPro if hard - else BrawlerBot, 'point': 'bottom_left'}, - {'type': BrawlerBotPro, 'point': 'bottom_right'} - if player_count > 2 else None, - ]}, - {'entries': [ - {'type': ChargerBot, 'path': 2}, - {'type': ChargerBot, 'path': 3}, - {'type': ChargerBot, 'path': 1} if hard else None, - {'type': ChargerBot, 'path': 2}, - {'type': ChargerBot, 'path': 3}, - {'type': ChargerBot, 'path': 1} if player_count > 2 - else None, - ]}, - {'entries': [ - {'type': BomberBotProShielded, 'path': 1} if hard - else None, - {'type': BomberBotProShielded, 'path': 2}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': BomberBotProShielded, 'path': 3}, - {'type': BomberBotProShielded, 'path': 3}, - {'type': ChargerBot, 'point': 'bottom_right'}, - {'type': ChargerBot, 'point': 'bottom_left'} - if player_count > 2 else None, - ]}, - {'entries': [ - {'type': TriggerBotPro, 'path': 1} - if hard else None, - {'type': TriggerBotPro, 'path': 1 if hard else 2}, - {'type': TriggerBotPro, 'path': 1 if hard else 2}, - {'type': TriggerBotPro, 'path': 1 if hard else 2}, - {'type': TriggerBotPro, 'path': 1 if hard else 2}, - {'type': TriggerBotPro, 'path': 1 if hard else 2}, - {'type': TriggerBotPro, 'path': 1 if hard else 2} - if player_count > 1 else None, - {'type': TriggerBotPro, 'path': 1 if hard else 2} - if player_count > 3 else None, - ]}, - {'entries': [ - {'type': TriggerBotProShielded if hard - else TriggerBotPro, 'point': 'bottom_left'}, - {'type': TriggerBotProShielded, - 'point': 'bottom_right'} - if hard else None, - {'type': TriggerBotProShielded, - 'point': 'bottom_right'} - if player_count > 2 else None, - {'type': BomberBot, 'path': 3}, - {'type': BomberBot, 'path': 3}, - {'type': 'spacing', 'duration': 5.0}, - {'type': BrawlerBot, 'path': 2}, - {'type': BrawlerBot, 'path': 2}, - {'type': 'spacing', 'duration': 5.0}, - {'type': TriggerBot, 'path': 1} if hard else None, - {'type': TriggerBot, 'path': 1} if hard else None, - ]}, - {'entries': [ - {'type': BomberBotProShielded, 'path': 2}, - {'type': BomberBotProShielded, 'path': 2} if hard - else None, - {'type': StickyBot, 'point': 'bottom_right'}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': StickyBot, 'point': 'bottom_right'} - if player_count > 2 else None, - {'type': BomberBotProShielded, 'path': 2}, - {'type': ExplodeyBot, 'point': 'bottom_left'}, - {'type': BomberBotProShielded, 'path': 2}, - {'type': BomberBotProShielded, 'path': 2} - if player_count > 1 else None, - {'type': 'spacing', 'duration': 5.0}, - {'type': StickyBot, 'point': 'bottom_left'}, - {'type': 'spacing', 'duration': 2.0}, - {'type': ExplodeyBot, 'point': 'bottom_right'}, - ]}, - ] # yapf: disable - elif self._preset in ['endless', 'endless_tournament']: + Wave(entries=[ + Spawn(TriggerBot, path=1) if hard else None, + Spawn(TriggerBot, path=2), + Spawn(TriggerBot, path=2), + Spawn(TriggerBot, path=3), + Spawn(BrawlerBotPro if hard else BrawlerBot, + point=Point.BOTTOM_LEFT), + Spawn(BrawlerBotPro, point=Point.BOTTOM_RIGHT + ) if player_count > 2 else None, + ]), + Wave(entries=[ + Spawn(ChargerBot, path=2), + Spawn(ChargerBot, path=3), + Spawn(ChargerBot, path=1) if hard else None, + Spawn(ChargerBot, path=2), + Spawn(ChargerBot, path=3), + Spawn(ChargerBot, path=1) if player_count > 2 else None, + ]), + Wave(entries=[ + Spawn(BomberBotProShielded, path=1) if hard else None, + Spawn(BomberBotProShielded, path=2), + Spawn(BomberBotProShielded, path=2), + Spawn(BomberBotProShielded, path=3), + Spawn(BomberBotProShielded, path=3), + Spawn(ChargerBot, point=Point.BOTTOM_RIGHT), + Spawn(ChargerBot, point=Point.BOTTOM_LEFT + ) if player_count > 2 else None, + ]), + Wave(entries=[ + Spawn(TriggerBotPro, path=1) if hard else None, + Spawn(TriggerBotPro, path=1 if hard else 2), + Spawn(TriggerBotPro, path=1 if hard else 2), + Spawn(TriggerBotPro, path=1 if hard else 2), + Spawn(TriggerBotPro, path=1 if hard else 2), + Spawn(TriggerBotPro, path=1 if hard else 2), + Spawn(TriggerBotPro, path=1 if hard else 2 + ) if player_count > 1 else None, + Spawn(TriggerBotPro, path=1 if hard else 2 + ) if player_count > 3 else None, + ]), + Wave(entries=[ + Spawn(TriggerBotProShielded if hard else TriggerBotPro, + point=Point.BOTTOM_LEFT), + Spawn(TriggerBotProShielded, point=Point.BOTTOM_RIGHT + ) if hard else None, + Spawn(TriggerBotProShielded, point=Point.BOTTOM_RIGHT + ) if player_count > 2 else None, + Spawn(BomberBot, path=3), + Spawn(BomberBot, path=3), + Spacing(duration=5.0), + Spawn(BrawlerBot, path=2), + Spawn(BrawlerBot, path=2), + Spacing(duration=5.0), + Spawn(TriggerBot, path=1) if hard else None, + Spawn(TriggerBot, path=1) if hard else None, + ]), + Wave(entries=[ + Spawn(BomberBotProShielded, path=2), + Spawn(BomberBotProShielded, path=2) if hard else None, + Spawn(StickyBot, point=Point.BOTTOM_RIGHT), + Spawn(BomberBotProShielded, path=2), + Spawn(BomberBotProShielded, path=2), + Spawn(StickyBot, point=Point.BOTTOM_RIGHT + ) if player_count > 2 else None, + Spawn(BomberBotProShielded, path=2), + Spawn(ExplodeyBot, point=Point.BOTTOM_LEFT), + Spawn(BomberBotProShielded, path=2), + Spawn(BomberBotProShielded, path=2 + ) if player_count > 1 else None, + Spacing(duration=5.0), + Spawn(StickyBot, point=Point.BOTTOM_LEFT), + Spacing(duration=2.0), + Spawn(ExplodeyBot, point=Point.BOTTOM_RIGHT), + ]), + ] + elif self._preset in {Preset.ENDLESS, Preset.ENDLESS_TOURNAMENT}: self._exclude_powerups = [] self._have_tnt = True @@ -480,7 +503,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): self._spawn_center[1], self._spawn_center[2] + random.uniform(-1.5, 1.5)) spaz = self.spawn_player_spaz(player, position=pos) - if self._preset in ['pro_easy', 'uber_easy']: + if self._preset in {Preset.PRO_EASY, Preset.UBER_EASY}: spaz.impact_scale = 0.25 # Add the material that causes us to hit the player-wall. @@ -580,7 +603,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): self._time_bonus_timer = None self._time_bonus_text = None - if self._preset in ['endless', 'endless_tournament']: + if self._preset in {Preset.ENDLESS, Preset.ENDLESS_TOURNAMENT}: won = False else: assert self._waves is not None @@ -604,7 +627,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): if won: # Completion achievements: - if self._preset in ['pro', 'pro_easy']: + if self._preset in {Preset.PRO, Preset.PRO_EASY}: self._award_achievement('Pro Runaround Victory', sound=False) if self._lives == self._start_lives: @@ -612,7 +635,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): if not self._player_has_picked_up_powerup: self._award_achievement('Precision Bombing', sound=False) - elif self._preset in ['uber', 'uber_easy']: + elif self._preset in {Preset.UBER, Preset.UBER_EASY}: self._award_achievement('Uber Runaround Victory', sound=False) if self._lives == self._start_lives: @@ -717,13 +740,13 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): t_sec = 0.0 base_delay = 0.5 delay = 0.0 - bot_types: List[Optional[Dict[str, Any]]] = [] + bot_types: List[Union[Spawn, Spacing, None]] = [] - if self._preset in ['endless', 'endless_tournament']: + if self._preset in {Preset.ENDLESS, Preset.ENDLESS_TOURNAMENT}: level = self._wavenum target_points = (level + 1) * 8.0 group_count = random.randint(1, 3) - entries = [] + entries: List[Union[Spawn, Spacing, None]] = [] spaz_types: List[Tuple[Type[SpazBot], float]] = [] if level < 6: spaz_types += [(BomberBot, 5.0)] @@ -811,13 +834,11 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): this_target_point_s *= 0.7 def _add_defender(defender_type: Tuple[Type[SpazBot], float], - pnt: str) -> Tuple[float, Dict[str, Any]]: - # FIXME: should look into this warning + pnt: Point) -> Tuple[float, Spawn]: + # This is ok because we call it immediately. # pylint: disable=cell-var-from-loop - return this_target_point_s * defender_type[1], { - 'type': defender_type[0], - 'point': pnt - } + return this_target_point_s * defender_type[1], Spawn( + defender_type[0], point=pnt) # Add defenders. defender_type1 = defender_types[random.randrange( @@ -829,10 +850,10 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): or (group == 2 and level > 5)): if random.random() < min(0.75, (level - 1) * 0.11): this_target_point_s, defender1 = _add_defender( - defender_type1, 'bottom_left') + defender_type1, Point.BOTTOM_LEFT) if random.random() < min(0.75, (level - 1) * 0.04): this_target_point_s, defender2 = _add_defender( - defender_type2, 'bottom_right') + defender_type2, Point.BOTTOM_RIGHT) spaz_type = spaz_types[random.randrange(len(spaz_types))] member_count = max( @@ -846,12 +867,9 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): this_path = random.randint(1, 3) # Random. else: this_path = path - entries.append({'type': spaz_type[0], 'path': this_path}) + entries.append(Spawn(spaz_type[0], path=this_path)) if spacing != 0.0: - entries.append({ - 'type': 'spacing', - 'duration': spacing - }) + entries.append(Spacing(duration=spacing)) if defender1 is not None: entries.append(defender1) @@ -866,15 +884,15 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): spacing = 1.0 else: spacing = 1.0 - entries.append({'type': 'spacing', 'duration': spacing}) + entries.append(Spacing(duration=spacing)) - wave = {'entries': entries} + wave = Wave(entries=entries) else: assert self._waves is not None wave = self._waves[self._wavenum - 1] - bot_types += wave['entries'] + bot_types += wave.entries self._time_bonus_mult = 1.0 this_flawless_bonus = 0 non_runner_spawn_time = 1.0 @@ -882,36 +900,27 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): for info in bot_types: if info is None: continue - bot_type = info['type'] - path = -1 - if bot_type is not None: - if bot_type == 'non_runner_delay': - non_runner_spawn_time += info['duration'] - continue - if bot_type == 'spacing': - t_sec += info['duration'] - continue - try: - path = info['path'] - except Exception: - path = random.randint(1, 3) - self._time_bonus_mult += bot_type.points_mult * 0.02 - this_flawless_bonus += bot_type.points_mult * 5 + if isinstance(info, Spacing): + t_sec += info.duration + continue + bot_type = info.type + path = info.path + self._time_bonus_mult += bot_type.points_mult * 0.02 + this_flawless_bonus += bot_type.points_mult * 5 # If its got a position, use that. - try: - point = info['point'] - except Exception: - point = 'start' + if info.point is not None: + point = info.point + else: + point = Point.START # Space our our slower bots. delay = base_delay delay /= self._get_bot_speed(bot_type) t_sec += delay * 0.5 - tcall = ba.Call(self.add_bot_at_point, point, { - 'type': bot_type, - 'path': path - }, 0.1 if point == 'start' else non_runner_spawn_time) + tcall = ba.Call( + self.add_bot_at_point, point, bot_type, path, + 0.1 if point is Point.START else non_runner_spawn_time) ba.timer(t_sec, tcall) t_sec += delay * 0.5 @@ -954,12 +963,12 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): # player could fill the whole map with them) self._last_wave_end_time = ba.time() + t_sec totalwaves = str(len(self._waves)) if self._waves is not None else '??' - txtval = ba.Lstr( - value='${A} ${B}', - subs=[('${A}', ba.Lstr(resource='waveText')), - ('${B}', str(self._wavenum) + - ('' if self._preset in ['endless', 'endless_tournament'] - else f'/{totalwaves}'))]) + txtval = ba.Lstr(value='${A} ${B}', + subs=[('${A}', ba.Lstr(resource='waveText')), + ('${B}', + str(self._wavenum) + ('' if self._preset in { + Preset.ENDLESS, Preset.ENDLESS_TOURNAMENT + } else f'/{totalwaves}'))]) self._wave_text = ba.NodeActor( ba.newnode('text', attrs={ @@ -987,20 +996,20 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): setattr(spaz, 'r_walk_speed', self._get_bot_speed(spaz_type)) def add_bot_at_point(self, - point: str, - spaz_info: Dict[str, Any], + point: Point, + spaztype: Type[SpazBot], + path: int, spawn_time: float = 0.1) -> None: """Add the given type bot with the given delay (in seconds).""" # Don't add if the game has ended. if self._game_over: return - pos = self.map.defs.points['bot_spawn_' + point][:3] - self._bots.spawn_bot(spaz_info['type'], + pos = self.map.defs.points[point.value][:3] + self._bots.spawn_bot(spaztype, pos=pos, spawn_time=spawn_time, - on_spawn_call=ba.Call(self._on_bot_spawn, - spaz_info['path'])) + on_spawn_call=ba.Call(self._on_bot_spawn, path)) def _update_time_bonus(self) -> None: self._time_bonus = int(self._time_bonus * 0.91) @@ -1022,7 +1031,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): def _update_scores(self) -> None: score = self._score - if self._preset == 'endless': + if self._preset is Preset.ENDLESS: if score >= 500: self._award_achievement('Runaround Master') if score >= 1000: @@ -1148,8 +1157,8 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]): ba.playsound(self._dingsound if importance == 1 else self._dingsoundhigh, volume=0.6) - except Exception as exc: - print('EXC in Runaround on SpazBotDiedMessage:', exc) + except Exception: + ba.print_exception('Error on SpazBotDiedMessage') # Normally we pull scores from the score-set, but if there's no # player lets be explicit.