2025-01-26 16:18:19 +05:30
|
|
|
# ba_meta require api 9
|
2024-02-01 11:57:50 +03:00
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
|
|
|
|
import babase
|
|
|
|
|
import bauiv1 as bui
|
|
|
|
|
import bascenev1 as bs
|
|
|
|
|
import random
|
|
|
|
|
from bascenev1lib.actor.onscreentimer import OnScreenTimer
|
|
|
|
|
from bascenev1lib.actor.spazbot import (
|
|
|
|
|
SpazBot, SpazBotSet,
|
|
|
|
|
BomberBot, BrawlerBot, BouncyBot,
|
2025-01-26 16:18:19 +05:30
|
|
|
ChargerBot, TriggerBot, ExplodeyBot)
|
2024-02-01 11:57:50 +03:00
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from typing import Any, List, Type, Optional
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Player(bs.Player['Team']):
|
|
|
|
|
"""Our player type for this game."""
|
|
|
|
|
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.death_time: Optional[float] = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Team(bs.Team[Player]):
|
|
|
|
|
"""Our team type for this game."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ba_meta export bascenev1.GameActivity
|
|
|
|
|
class BotShowerGame(bs.TeamGameActivity[Player, Team]):
|
|
|
|
|
"""A babase.MeteorShowerGame but replaced with bots."""
|
|
|
|
|
|
|
|
|
|
name = 'Bot Shower'
|
|
|
|
|
description = 'Survive from the bots.'
|
|
|
|
|
available_settings = [
|
|
|
|
|
bs.BoolSetting('Spaz', default=True),
|
|
|
|
|
bs.BoolSetting('Zoe', default=True),
|
|
|
|
|
bs.BoolSetting('Kronk', default=True),
|
|
|
|
|
bs.BoolSetting('Snake Shadow', default=True),
|
|
|
|
|
bs.BoolSetting('Mel', default=True),
|
|
|
|
|
bs.BoolSetting('Jack Morgan', default=True),
|
|
|
|
|
bs.BoolSetting('Easter Bunny', default=True),
|
|
|
|
|
bs.BoolSetting('Epic Mode', default=False),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
announce_player_deaths = True
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
|
|
|
|
return ['Football Stadium', 'Hockey Stadium']
|
|
|
|
|
|
|
|
|
|
def __init__(self, settings: dict) -> None:
|
|
|
|
|
super().__init__(settings)
|
|
|
|
|
self._epic_mode = settings['Epic Mode']
|
|
|
|
|
self._last_player_death_time: Optional[float] = None
|
|
|
|
|
self._timer: Optional[OnScreenTimer] = None
|
|
|
|
|
self._bots: Optional[SpazBotSet] = None
|
|
|
|
|
self._bot_type: List[SpazBot] = []
|
|
|
|
|
|
|
|
|
|
if bool(settings['Spaz']) == True:
|
|
|
|
|
self._bot_type.append(BomberBot)
|
|
|
|
|
else:
|
|
|
|
|
if BomberBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(BomberBot)
|
|
|
|
|
if bool(settings['Zoe']) == True:
|
|
|
|
|
self._bot_type.append(TriggerBot)
|
|
|
|
|
else:
|
|
|
|
|
if TriggerBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(TriggerBot)
|
|
|
|
|
if bool(settings['Kronk']) == True:
|
|
|
|
|
self._bot_type.append(BrawlerBot)
|
|
|
|
|
else:
|
|
|
|
|
if BrawlerBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(BrawlerBot)
|
|
|
|
|
if bool(settings['Snake Shadow']) == True:
|
|
|
|
|
self._bot_type.append(ChargerBot)
|
|
|
|
|
else:
|
|
|
|
|
if ChargerBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(ChargerBot)
|
|
|
|
|
if bool(settings['Jack Morgan']) == True:
|
|
|
|
|
self._bot_type.append(ExplodeyBot)
|
|
|
|
|
else:
|
|
|
|
|
if ExplodeyBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(ExplodeyBot)
|
|
|
|
|
if bool(settings['Easter Bunny']) == True:
|
|
|
|
|
self._bot_type.append(BouncyBot)
|
|
|
|
|
else:
|
|
|
|
|
if BouncyBot in self._bot_type:
|
|
|
|
|
self._bot_type.remove(BouncyBot)
|
|
|
|
|
|
|
|
|
|
self.slow_motion = self._epic_mode
|
|
|
|
|
self.default_music = (bs.MusicType.EPIC
|
|
|
|
|
if self._epic_mode else bs.MusicType.SURVIVAL)
|
|
|
|
|
|
|
|
|
|
def on_begin(self) -> None:
|
|
|
|
|
super().on_begin()
|
|
|
|
|
self._bots = SpazBotSet()
|
|
|
|
|
self._timer = OnScreenTimer()
|
|
|
|
|
self._timer.start()
|
|
|
|
|
|
|
|
|
|
if self._epic_mode:
|
|
|
|
|
bs.timer(1.0, self._start_spawning_bots)
|
|
|
|
|
else:
|
|
|
|
|
bs.timer(5.0, self._start_spawning_bots)
|
|
|
|
|
|
|
|
|
|
bs.timer(5.0, self._check_end_game)
|
|
|
|
|
|
|
|
|
|
def spawn_player(self, player: Player) -> None:
|
|
|
|
|
spaz = self.spawn_player_spaz(player)
|
|
|
|
|
spaz.connect_controls_to_player(
|
|
|
|
|
enable_punch=False,
|
|
|
|
|
enable_bomb=False,
|
|
|
|
|
enable_pickup=False)
|
|
|
|
|
return spaz
|
|
|
|
|
|
|
|
|
|
def on_player_join(self, player: Player) -> None:
|
|
|
|
|
if self.has_begun():
|
|
|
|
|
bui.screenmessage(
|
|
|
|
|
babase.Lstr(resource='playerDelayedJoinText',
|
2024-02-01 08:58:54 +00:00
|
|
|
subs=[('${PLAYER}', player.getname(full=True))]),
|
2024-02-01 11:57:50 +03:00
|
|
|
color=(1, 1, 0),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert self._timer is not None
|
|
|
|
|
player.death_time = self._timer.getstarttime()
|
|
|
|
|
return
|
|
|
|
|
self.spawn_player(player)
|
|
|
|
|
|
|
|
|
|
def handlemessage(self, msg: Any) -> Any:
|
|
|
|
|
if isinstance(msg, bs.PlayerDiedMessage):
|
|
|
|
|
curtime = bs.time()
|
|
|
|
|
msg.getplayer(Player).death_time = curtime
|
|
|
|
|
|
|
|
|
|
bs.timer(1.0, self._check_end_game)
|
|
|
|
|
else:
|
|
|
|
|
super().handlemessage(msg)
|
|
|
|
|
|
|
|
|
|
def _start_spawning_bots(self) -> None:
|
|
|
|
|
bs.timer(1.2, self._spawn_bot, repeat=True)
|
|
|
|
|
bs.timer(2.2, self._spawn_bot, repeat=True)
|
|
|
|
|
|
|
|
|
|
def _spawn_bot(self) -> None:
|
|
|
|
|
assert self._bots is not None
|
2024-02-01 08:58:54 +00:00
|
|
|
self._bots.spawn_bot(random.choice(self._bot_type), pos=(
|
|
|
|
|
random.uniform(-11, 11), (9.8 if self.map.getname() == 'Football Stadium' else 5.0), random.uniform(-5, 5)))
|
2024-02-01 11:57:50 +03:00
|
|
|
|
|
|
|
|
def _check_end_game(self) -> None:
|
|
|
|
|
living_team_count = 0
|
|
|
|
|
for team in self.teams:
|
|
|
|
|
for player in team.players:
|
|
|
|
|
if player.is_alive():
|
|
|
|
|
living_team_count += 1
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if living_team_count <= 1:
|
|
|
|
|
self.end_game()
|
|
|
|
|
|
|
|
|
|
def end_game(self) -> None:
|
|
|
|
|
cur_time = bs.time()
|
|
|
|
|
assert self._timer is not None
|
|
|
|
|
start_time = self._timer.getstarttime()
|
|
|
|
|
|
|
|
|
|
for team in self.teams:
|
|
|
|
|
for player in team.players:
|
|
|
|
|
survived = False
|
|
|
|
|
|
|
|
|
|
if player.death_time is None:
|
|
|
|
|
survived = True
|
|
|
|
|
player.death_time = cur_time + 1
|
|
|
|
|
|
|
|
|
|
score = int(player.death_time - self._timer.getstarttime())
|
|
|
|
|
if survived:
|
|
|
|
|
score += 50
|
|
|
|
|
self.stats.player_scored(player, score, screenmessage=False)
|
|
|
|
|
|
|
|
|
|
self._timer.stop(endtime=self._last_player_death_time)
|
|
|
|
|
|
|
|
|
|
results = bs.GameResults()
|
|
|
|
|
|
|
|
|
|
for team in self.teams:
|
|
|
|
|
|
|
|
|
|
longest_life = 0.0
|
|
|
|
|
for player in team.players:
|
|
|
|
|
assert player.death_time is not None
|
|
|
|
|
longest_life = max(longest_life,
|
|
|
|
|
player.death_time - start_time)
|
|
|
|
|
|
|
|
|
|
results.set_team_score(team, int(1000.0 * longest_life))
|
|
|
|
|
|
2024-02-01 08:58:54 +00:00
|
|
|
self.end(results=results)
|