# Ported to api 8 by brostos using baport.(https://github.com/bombsquad-community/baport) # ba_meta require api 8 from __future__ import annotations from typing import TYPE_CHECKING import babase import bauiv1 as bui import bascenev1 as bs import random from bascenev1lib.actor.spazbot import BrawlerBot, SpazBotSet, SpazBot, SpazBotDiedMessage from bascenev1lib.actor.bomb import Bomb from bascenev1lib.actor.spaz import Spaz from bascenev1lib.actor.onscreentimer import OnScreenTimer if TYPE_CHECKING: from typing import Any, List, Type, Optional # def ba_get_api_version(): # return 6 def ba_get_levels(): return [babase._level.Level( 'Bot Chase', gametype=BotChaseGame, settings={}, preview_texture_name='footballStadiumPreview')] class Player(bs.Player['Team']): """Our player type for this game""" def __init__(self) -> None: super().__init__() self.death_time: Optional[float] = None class MrSpazBot(SpazBot): """Our bot type for this game""" character = 'Spaz' run = True charge_dist_min = 10.0 charge_dist_max = 9999.0 charge_speed_min = 1.0 charge_speed_max = 1.0 throw_dist_min = 9999 throw_dist_max = 9999 class Team(bs.Team[Player]): """Our team type for this minigame""" # ba_meta export bascenev1.GameActivity class BotChaseGame(bs.TeamGameActivity[Player, Team]): """Our goal is to survive from spawning bots""" name = 'Bot Chase' description = 'Try to survive from bots!' available_settings = [ 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'] @classmethod def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool: # Coop session unused return (issubclass(sessiontype, bs.FreeForAllSession) or issubclass(sessiontype, bs.DualTeamSession) or issubclass(sessiontype, bs.CoopSession)) def __init__(self, settings: dict): super().__init__(settings) self._bots = SpazBotSet() self._epic_mode = bool(settings['Epic Mode']) self._timer: Optional[OnScreenTimer] = None self._last_player_death_time: Optional[float] = None if self._epic_mode: self.slow_motion = True self.default_music = (bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH) def on_player_join(self, player: Player) -> None: if self.has_begun(): bs.broadcastmessage( babase.Lstr(resource='playerDelayedJoinText', subs=[('${PLAYER}', player.getname(full=True))]), color=(0, 1, 0), ) assert self._timer is not None player.death_time = self._timer.getstarttime() return self.spawn_player(player) def on_player_leave(self, player: Player) -> None: super().on_player_leave(player) self._check_end_game() def spawn_player(self, player: Player) -> bs.Actor: spaz = self.spawn_player_spaz(player) spaz.connect_controls_to_player(enable_punch=True, enable_bomb=True, enable_pickup=True) spaz.bomb_count = 3 spaz.bomb_type = 'normal' # cerdo gordo spaz.node.color_mask_texture = bs.gettexture('melColorMask') spaz.node.color_texture = bs.gettexture('melColor') spaz.node.head_mesh = bs.getmesh('melHead') spaz.node.hand_mesh = bs.getmesh('melHand') spaz.node.torso_mesh = bs.getmesh('melTorso') spaz.node.pelvis_mesh = bs.getmesh('kronkPelvis') spaz.node.upper_arm_mesh = bs.getmesh('melUpperArm') spaz.node.forearm_mesh = bs.getmesh('melForeArm') spaz.node.upper_leg_mesh = bs.getmesh('melUpperLeg') spaz.node.lower_leg_mesh = bs.getmesh('melLowerLeg') spaz.node.toes_mesh = bs.getmesh('melToes') spaz.node.style = 'mel' # Sounds cerdo gordo mel_sounds = [bs.getsound('mel01'), bs.getsound('mel02'), bs.getsound('mel03'), bs.getsound('mel04'), bs.getsound('mel05'), bs.getsound('mel06'), bs.getsound('mel07'), bs.getsound('mel08'), bs.getsound('mel09'), bs.getsound('mel10')] spaz.node.jump_sounds = mel_sounds spaz.node.attack_sounds = mel_sounds spaz.node.impact_sounds = mel_sounds spaz.node.pickup_sounds = mel_sounds spaz.node.death_sounds = [bs.getsound('melDeath01')] spaz.node.fall_sounds = [bs.getsound('melFall01')] spaz.play_big_death_sound = True return spaz def on_begin(self) -> None: super().on_begin() self._bots.spawn_bot(MrSpazBot, pos=(random.choice( [1, -1, 2, -2]), 1.34, random.choice([1, -1, 2, -2])), spawn_time=2.0) self._bots.spawn_bot(MrSpazBot, pos=(random.choice( [1, -1, 2, -2]), 1.34, random.choice([1, -1, 2, -2])), spawn_time=2.0) self._timer = OnScreenTimer() self._timer.start() bs.timer(10.0, self._spawn_this_bot, repeat=True) bs.timer(5.0, self._check_end_game) def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): super().handlemessage(msg) curtime = bs.time() msg.getplayer(Player).death_time = curtime if isinstance(self.session, bs.CoopSession): babase.pushcall(self._check_end_game) self._last_player_death_time = curtime else: bs.timer(1.0, self._check_end_game) elif isinstance(msg, SpazBotDiedMessage): self._spawn_this_bot() else: return super().handlemessage(msg) return None def _spawn_this_bot(self) -> None: self._bots.spawn_bot(MrSpazBot, pos=(random.choice( [1, -1, 2, -2]), 1.34, random.choice([1, -1, 2, -2])), spawn_time=2.0) 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 isinstance(self.session, bs.CoopSession): if living_team_count <= 0: self.end_game() else: 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)) self.end(results=results)