Modernized runaround code

This commit is contained in:
Eric Froemling 2020-06-02 20:11:10 -07:00
parent 5b4282eb11
commit ed102842c5
2 changed files with 270 additions and 260 deletions

View File

@ -1752,6 +1752,7 @@
<w>spazappearance</w> <w>spazappearance</w>
<w>spazbot</w> <w>spazbot</w>
<w>spazfactory</w> <w>spazfactory</w>
<w>spaztype</w>
<w>spazzes</w> <w>spazzes</w>
<w>spcall</w> <w>spcall</w>
<w>spcstr</w> <w>spcstr</w>

View File

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